前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《深入理解Java虚拟机》摘抄(1-3章)

《深入理解Java虚拟机》摘抄(1-3章)

作者头像
喜欢天文的pony站长
发布2020-06-29 12:05:59
4130
发布2020-06-29 12:05:59
举报
文章被收录于专栏:RabbitMQ实战RabbitMQ实战

JDK

Java Development Kit

Java开发工具包

JRE

Java Runtime Environment

Java运行环境

JVM

Java Virtual Machine

Java虚拟机

  • JDK结构体系图

图片来源:https://docs.oracle.com/javase/8/docs/

  • Java的优点
  • OpenJDK 与 Oracle JDK

查看安装的是oracleJDK还是openJDK openJDK则显示 openjdk version "1.8.0_144" OpenJDK Runtime Environment (build 1.8.0_144-b01) OpenJDK 64-Bit Server VM (build 25.144-b01, mixed mode) 2.2 运行时数据区域

  • 程序计数器 Program Counter Register 当前线程执行的字节码的行号指示器,通过这个计数器来指定下一条执行的字节码指令(程序代码)。分支,循环,跳转,异常处理,线程恢复等都依赖这个程序计数器。 对于多线程,每个线程都有一个独立的,互不干扰的程序计数器。(称这部分区域为线程私有内存)
  • Java虚拟机栈 Java Virtual Machine Stacks 与程序计数器一样也是线程私有的,生命周期与线程相同。Java虚拟机栈描述的是Java方法执行的内存模型:每个Java方法在执行的时候都会创建一个栈帧用来存储局部变量表,操作数栈,动态链接,方法出口等信息,每个方法从调用到执行完成的过程,就对应一个栈帧在Java虚拟机栈中的入栈到出栈的过程。 如果线程请求的栈深度超过了虚拟机所允许的栈深度,将会抛出StackOverFlowError异常。 因为大部分虚拟机支持栈的动态扩展,如果动态扩展时无法申请到足够的内存,则会抛出OutOfMemoryError异常,OOM
  • 本地方法栈 Native Method Stack 与Java虚拟机栈的作用类似。区别只是Java虚拟机栈是为虚拟机执行Java方法(字节码)服务,而本地方法栈是为虚拟机执行Native方法服务。(Sun Hotspot虚拟机将这两块内存区域合并) 异常同上
  • Java堆 Java Heap Java堆是被所有线程共享的内存区域,在虚拟机启动的时候创建,此内存区域的唯一目的就是存放对象实例(对象的引用在栈Stack)。 Java堆也是内存回收器管理的主要区域,因此也被称为GC堆(Garbage Collected Heap)。 可通过-Xmx和-Xms控制 如果堆内存不足,会抛出OutOfMemoryError异常
  • 方法区 Method Area(Non-Heap) 方法区也是线程共享的内存区域。用于存放已经被Java虚拟机加载的类信息,常量,静态变量,即时编译器编译的代码等数据。 当方法区无法满足内存分配的需求时,将抛出OOM。
  • 运行时常量池 Runtime Constant Pool 运行时常量池是方法区的一部分。Class文件中除了有类的版本,字段,方法,接口等信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。OOM

# 2.3 HotSpot虚拟机对象

  • 对象的创建 当虚拟机遇到一条New指令,首先去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号代表的类是否已经被加载,解析和初始化。如果没有,那么必须先执行相应的类加载过程。 在类加载检查通过之后,接下来虚拟机将为新生对象分配内存,把一块确定大小的内存从Java堆中划分出来。对象所需要的内存大小在类加载完成之后就可以完全确认。内存分配完成之后,虚拟机需要将分配到的内存空间都初始化为零值,这一步操作保证了对象的实例字段在Java代码中可以不赋初始值就直接使用,程序能访问到的这些字段的数据类型所对应的零值。这也是为什么实例变量可以不进行手动初始化即可使用,而方法局部变量必须要手动进行初始化。
  • 对象的访问定位建立对象是为了使用对象,Java程序需要通过栈上的reference数据来操作堆上的具体对象。目前主流的访问方式有使用句柄和直接指针两种。
  • 如果使用句柄(稳定)。那么Java堆中需要划分一块内存用来存放句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息。 优点:因为句柄地址是固定的,所以对象本身被移动,句柄地址是不需要改动的(句柄映射的对象指针才需要改动),所以reference不需要改动。
  • 如果直接使用指针访问(速度快)。HotSpot虚拟机即使用指针访问。那么reference中存储的就直接是对象的堆内存地址。并且Java堆对象的布局中就必须考虑如何放置访问类型数据的相关信息。

2.4 OutOfMemoryError异常 -Xms20M 堆的最小值 -Xmx20M 堆的最大值 -XX:+HeapDumpOnOutOfMemeoryError 可以让虚拟机在出现内存溢出时Dump出当前的内存堆转储快照以便事后进行分析。 -Xoss 设置本地方法栈大小(因为HotSpot虚拟机将本地方法栈与虚拟机栈合并,所以该参数在HotSpot虚拟机无效) -Xss2M 虚拟机栈大小 方法区内存大小 -XX:PermSize=10M (Java8中已被删除) -XX:MaxPermSize=10M (Java8中已被删除)

  • 模拟Java堆内存OutOfMemoryError

/** * 模拟Java堆内存OutOfMemoryError * * @param args */ public static void main(String[] args) { List<User> list = new ArrayList<>(); while (true) { list.add(new User()); } }

  • Java Heap space
  • PermSize和MaxPermSize在Java8中已被删除
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 喜欢天文 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档