JVM基本知识总结

大概两三个月之前阅读了《深入理解Java虚拟机》(周志明著),也为了加深印象,这里简单的做下总结,想完整点了解JVM知识的也可以阅读本书,书写的不错,相当通俗易懂。


 

第一部分 内存管理机制:

Java内存区域与内存溢出:

Java内存区域分为堆、栈(Java虚拟机栈和本地方法栈,不过对于hotspot来讲,是一致的)、方法区、程序计数器、直接内存区域(NIO的allocateByDireactMemory)等。借用@兰亭风雨 的图片一张

其中方法区用于加载类信息、常量、静态变量、即时编译器编译后的代码等数据的存储(运行时常量池也是方法区的一部分,Class文件的结构包括魔数、版本号、域、接口、方法等信息,常量池(Class文件常量池),用于存放编译器生成的各种字面量和符号引用)、堆区用于存放对象实例、栈的话通过压入或者弹出栈帧来控制程序,每个方法被执行的时候都会同时创建一个栈帧,一个栈帧需要分配多少内存,不会受到程序运行期变量数据的影响,而仅仅取决于具体的虚拟机实现。

内存溢出异常可以发生在栈、方法区、以及堆区(又被成为GC堆)。栈区如果发生溢出,可能是由于栈深度超出或者是线程栈的数量太多。方法区溢出原因可能是动态生成大量类或者是使用了String.intern()方法,堆区是可能由于new了大量的对象。

JVM垃圾回收:

要回收一个对象,首先要判断该对象是否无用,有两种方法:引用计数法和图的可达性分析(GC ROOTS:栈帧中的引用对象、方法区静态常量引用对象、本地方法引用对象)的方法。其中引用分四个类别:强引用、软引用、弱引用、影子引用(虚引用),引用强度依次减弱。JVM垃圾回有三种算法,复制、标记删除、标记整理,同时采用分代分代算法,基本上Young代采用复制,Old代采用标记删除或者整理。安全点(safepoint),JVM只有执行到安全点才会进行GC工作,安全点一般在方法调用、循环跳转、异常跳转等,有两种方法使得程序跑到安全点,分为抢占式和主动式。

Hotspot的垃圾收集器不算G1的话有6种,其中Serial(串行)、ParNew、Parallel作用于新生代,CMS、Serial Old、Parallel Old作用于老年代。具体的内容有空再补充上。基本上Web服务器采用CMS+ParNew的组合,降低响应时间。CMS的四次标记过程也是需要记住的,分别是初始标记、并发标记、重新标记、并发清楚。