-
新生代占堆内存的1/3,其中Eden占新生代的80%,From和To各占10%
-
老年代占堆内存的2/3
-
对象分配的规则
- 对象主要分配在新生代的Eden区
- 如果启动了本地线程分配缓冲,将按线程优先级在TLAB上分配
- 少数情况下也可能直接分配在老年代上
-
GC参数指定垃圾回收:
-Xms20M、-Xmx20M、-Xmn10M这三个参数分别限制了Java堆大小为20MB,不可扩展,其中10MB分配给老年代。-Xx:Servivor=8决定了新生代中Eden区与两个Survivor区的空间比例是8:1
-
新生代与老年代:
新生代GC(Minor GC):指发生在新生代的垃圾收集动作,因为Java对象大多具备朝生夕灭的特性,所以Minor GC非常频繁,回收老年代GC(Major GC/Full GC):指发生在老年代的GC,出现了Major GC,经常会伴随至少一次的Minor GC(非绝对的,在Parallel Scavebge收集器的收集策略里就有直接进行Major GC的策略选择过程)。Major GC的速度一般会比Minor GC慢10倍以上。
Full GC:全局扫描,回收年轻代和老年代
-
大对象的分配:
- 所谓的大对象是指,需要大量连续的内存空间发的Java对象,最典型的就是很长的字符串以及数组
- 虚拟机提供了一个-XX:PretenureSizeThrehold参数,令大于这个设置值得对象直接在老年代分配。这样做的目的是避免在Eden区及两个Survivor区之间发生大量的内存复制。
-
大对象配置
- -verbose:gc -XX:+PrintGCDetails 开启GC打印日志
- -XX:+UseSerialGC 配置垃圾回收器
- -Xms20M 设置JVM初始内存为20M
- -Xmx20M 设置JVM最大内存为20M
- -Xmn10M 设置年轻代内存大小为10M
-
逃逸分析:逃逸分析的基本行为就是分析对象动态作用域,当一个对象在方法中被定义后,它可能被外部方法锁引用,称为方法逃逸。甚至有可能被外部线程访问到,比如赋值给类变量或可以在其他线程中访问的实例变量,称为线程逃逸
public class EscapeTest { public static Object obj = null; public void variableEscape(){ obj = new Object(); //发生了逃逸 } public Object methodEscape(){ return new Object(); //方法逃逸 } }
- -XX :+DoEscapeAnalysis 开启逃逸分析(jdk1.8默认开启)
- -XX :-DoEscapeAnalysis 关闭逃逸分析
-
栈上分配:把方法中的变量和对象分配到栈上,方法执行完后自动销毁,而不需要垃圾回收的介入,从而提高系统性能。
public class EscapeTest { public static void alloc(){ byte[] b = new byte[2]; //开启逃逸分析在栈上分配,关闭逃逸分析在堆上分配 b[0] = 1; } public static void main(String[] args) { long start = System.currentTimeMillis(); for (int i = 0; i < 100000000; i++) { alloc(); } long end = System.currentTimeMillis(); System.out.println(end - start); } }
07-25