JVM 结构及垃圾回收

Runtime Data Area 运行时数据区

1. method area  

线程共享

存放已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等信息。多个线程同时加载一个类时,只有一个会请求Class Loader加载,另一个会等待。

 

MetaSpace 元数据空间

从JDK1.8 开始method area被metaspace完全取代。metaspace使用本地内存存放数据,意味着java.lang.OutOfMemoryError: PermGen的空间问题将不复存在,并且不再需要调整和监控这个内存空间。一个新的参数 (MaxMetaspaceSize)可以使用。允许你来限制用于类元数据的本地内存。如果没有特别指定,元空间将会根据应用程序在运行时的需求动态设置大小。

 

2. java stack

线程私有 每创建一个线程,虚拟机就会创建一个java stack,它表示java方法执行的内存模型. 每调用一个方法,就会生成一个栈帧(stack frame)用于存放方法的本地变量、 操作栈、方法出口等信息,当这个方法执行完后,就会弹出相应的栈帧。

如果请求的栈深度过大,虚拟机就会抛出StackOverflowError。如果虚拟机的实现中允许java stack动态扩展,当内存不足的时候,会抛出OutOfMemoryError。

扫描二维码关注公众号,回复: 489031 查看本文章

调整栈空间大小: java -Xss1m  默认1M 

 

method frame 方法帧

分为三部分:Local Variables 局部变量区、 Operand Stack 操作数栈 和 Frame Data 帧数据区

 

3.  Native Method Stack

与java Stack类似,只是执行本地方法时使用。

 

4.  Heap

线程共享

虚拟机中用于存放对象和数组实例的地方,垃圾回收的主要区域就是这里(还可能有方法区)。

设置堆大小: 

-Xmx128m (默认物理内存的1/4)   

-Xms16m

Heap 可以细分为:

新生代

Eden区

Survivor 1区

Survivor 2区

 老年代

 

4.Program Counter Register 程序计数器

线程私有

记录当前线程执行的指令地址,用于多线程间切换时恢复每一个线程的执行位置。 如果当前执行的是本地方法,存储的值是Undefined

 

 

Minor GC 和 Full GC

Minor GC:新生代GC,指发生在新生代的垃圾收集动作

如果Eden空间占满了, 会触发 minor GC。 Minor GC 后仍然存活的对象会被复制到S0中去。这样Eden就被清空可以分配给新的对象。又触发了一次 Minor GC , S0和Eden中存活的对象被复制到S1中, 并且S0和Eden被清空。 在同一时刻, 只有Eden和一个Survivor Space同时被操作。

当每次对象从Eden复制到Survivor Space或者从Survivor Space中的一个复制到另外一个,有一个计数器会自动增加值。 默认情况下如果复制发生超过16次, JVM 会停止复制并把他们移到老年代中去。

Major GC/Full GC:老年代GC,指发生在老年代的GC。

如果一个对象不能在Eden中被创建,它会直接被创建在老年代中。 如果老年代的空间被占满会触发老年代的 GC,也被称为 Full GC。full GC 是一个压缩处理过程,所以它比Minor GC要慢很多。

 

 

 

Minor GC ,Full GC 触发条件

Minor GC触发条件:

当Eden区满时,触发Minor GC。

Full GC触发条件:

(1)调用System.gc时,系统建议执行Full GC,但是不必然执行

(2)老年代空间不足

(3)方法去空间不足

(4)通过Minor GC后进入老年代的平均大小大于老年代的可用内存

(5)由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小

 

 

如何确定某个对象是“垃圾

1.引用计数器算法

给对象中添加一个引用计数器,每当有一个地方引用它时,计数器的值加1;当引用失效时,计数器的值减;当该对象的计数器的值为0时,标志该对象失效。

2.跟搜索算法

基本思路:通过一系列的名为“GCRoots”的对象作为起始点,从这些节点开始向下搜索,搜索过的路径称为引用链,当一个对象到GCRoots没有任何引用链相连(用图论的话来说就是从GC Roots到这个对象不可达)时,则证明对象是不可用的。

 

 

垃圾收集算法 及 垃圾收集器

http://www.cnblogs.com/dolphin0520/p/3783345.html

 

 

查看Jvm状态的工具

jvisualvm.exe

jmc.exe

jconsole.exe

 

 

参数设置

堆设置:

-Xms 初始堆大小

-Xmx 最大堆大小

-XX:NewSize=n 年轻代大小

-XX:NewRatio=n 设置年轻代和年老代的比值。如n=3表示年轻代和年老代的比值为1:3。默认n=2, 即年轻代占Heap大小的1/3, 年老代占2/3。

-XX:SurvivorRatio=n 设置Eden区与两个Survivor区的比值。如n=3,表示Eden区与两个Survivor区的比值为3:1:1, Eden区占整个年轻代大小的3/5。默认n=1。

-XX:MaxPermSize=n 设置持久代大小, 即方法区的大小。

-XX:MaxTenuringThreshold=n  默认n=5  设置垃圾最大存活阀值。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。

-XX:MaxPermSize=128m 设置永久代的大小,JDK1.8以后这个参数被废除

-XX:MetaspaceSize   JDK8里的Metaspace

-XX:MaxMetaspaceSize   JDK8里的Metaspace  超过这个值会触发垃圾回收

 

 

收集器设置

-XX:+UseSerialGC  设置串行收集器

-XX:+UseParallelGC 设置并行收集器

-XX:+ParallelGCThreads=4  设置并行收集器线程数

-XX:+UseParallelOldGC 设置并行年老代收集器 

-XX:+UseConcMarkSweepGC 设置CMS收集器

-XX:ParallelCMSThreads=4 设置CMS收集器线程数

-XX:+UseG1GC 设置G1收集器

 

 

垃圾回收统计信息

-XX:+PrintGC

-XX:+PrintGCDetails

-XX:+PrintGCTimeStamps

-Xloggc:filename  将日志写入到文件

 

 

 参考:

<怎么在面试时回答Java垃圾回收机制(GC)相关问题> https://www.zhihu.com/question/35164211

<Java垃圾回收机制> http://www.cnblogs.com/dolphin0520/p/3783345.html

<JVM 参数> http://www.tuicool.com/articles/RNjUfa

<Java 8最快的垃圾搜集器是什么> http://www.importnew.com/16533.html

<从PermGen 到 MetaSpace>http://blog.csdn.net/zhyhang/article/details/17246223

猜你喜欢

转载自oracle-api.iteye.com/blog/2367598