《深入理解JVM虚拟机》读书笔记(一)

Java 发表评论

此书一共分为5个部分:

  1. 走近Java
  2. 自动内存管理机制
  3. 虚拟机执行子系统
  4. 程序编译与代码优化
  5. 高效并发

这里,我直接跳过第一部分的内容,开始第二部分的内容。此部分包括:

  • Java内存区域与内存溢出异常
  • 垃圾收集器与内存分配策略
  • 虚拟机性能监控与故障处理工具
  • 调优案例分析与实战

开记!!!

首先引用原书中的一句话,“Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”, 墙外面的人想进去, 墙里面的人却想出来。

一. 运行时数据区域

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。

程序计数器:一块很小的内存区域,用来记录程序下一条字节码指令的地址,如果线程正在执行的是一个Java方法,这个程序计数器记录的是正在执行的虚拟机字节码指令地址;如果正在执行的是一个Native方法,这个计数器的值则为空。

此区域是Java虚拟机规范中没有规定任何OutofMemoryError情况的区域。


虚拟机栈:线程私有,生命周期与线程相同,这个区域描述的是Java方法执行的内存模型:每个方法在执行的时候都会创建一个栈帧(Stack Frame)用于存储局部变量表,操作数栈,动态链接,方法出口等信息。
在虚拟机规范中,这个区域规定了2种异常:一是线程请求的栈深度大于虚拟机所允许的深度将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展,如果申请到足够的内存,就会抛出OutOfMemoryError异常。

本地方法栈:与虚拟机栈类型,只不过本地方法栈是调用本地的Native方法,与虚拟机栈一样会抛出StackOverflowError及OutOfMemoryError异常。

Java堆:所有对象实例及数组都要在堆上分配(Java虚拟机规范描述),但是随着JIT编译器的发展与逃逸分析技术逐渐成熟,栈上分配,标量替换优化技术将会导致一些微妙的变化。
Java堆可以分为新生代和老年代;再细致一点新生代分为Eden空间,From Survivors空间,To Survivors空间。进一步划分是为了更好的回收内存,跟回收算法有关系。
虚拟机规范中规定,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可。会发生OutOfMemoryError异常。

方法区:跟Java堆一样是线程共享的内存区域,它用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。虚拟机规范把这个区域描述为堆的一个逻辑部分,但它有一个别名叫非堆(Non-Heap),会发生OutOfMemoryError异常。

运行时常量池:是方法区的一部分,用来存储各种字面量及符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。
常量池具有动态性,运行期间也可能将新的常量放入池中,这种特性用的比较多的是String的intern()方法。会发生OutOfMemoryError异常。

直接内存:并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,但这部分也被频繁的使用,最典型的应用便是JDK1.4新增的NIO通过DirectByteBuffer对象来操作这部分内存,这样避免了Java堆跟Native堆中数据来回复制数据的开销。

二. HotSpot虚拟机对象探秘

Java对象的创建过程:只提供一个图,细节太多。


Java对象的内存分布:

三个区域–对象头Header,实例数据Instance Data,对齐数据Padding

其中对象头分为2个部分,分别是Mark word与类型指针(指向它的类元数据)

发表评论

电子邮件地址不会被公开。 必填项已用*标注

昵称 *