一 点睛
1 存储在 JVM 中的 Java 对象可以被划分为两类。
-
一类是生命周期较短的瞬时对象,这类对象的创建和消亡都非常迅速,它的特点是生命周期短,可及时回收。
-
一类对象的生命周期非常长(比如一些连接的对象),在某些极端的情况下还能够与JVM的生命周期保持一致。
2 Java 堆区进一步细分的话,可以划分为年轻代(YoungGen)和老年代(oldGen)。
3 年轻代又可以划分为 Eden(圣经中的故事) 空间、Survivor0 空间和 Survivor1 空间(有时也叫做 from 区、to 区)。
下面这个参数开发中一般不会用。
从这张图中,得出如下结论。
Eden:From:to = 8:1:1
新生代:老年代 = 1:2
配置新生代与老年代在堆结构的占比。
-
默认-XX:NewRatio=2,表示新生代占1,老年代占2,新生代占整个堆的 1/3。
-
可以修改-XX:NewRatio=4,表示新生代占1,老年代占4,新生代占整个堆的 1/5。
当发现在整个项目中,生命周期长的对象偏多,那么就可以通过调整老年代的大小,来进行调优。
在 HotSpot 中,Eden 空间和另外两个 survivor 空间缺省所占的比例是8:1:1。
开发人员可以通过选项“-XX:SurvivorRatio”调整这个空间比例。比如-XX:SurvivorRatio=8
几乎所有的 Java 对象都是在 Eden 区被 new 出来的。
绝大部分的 Java 对象的销毁都在新生代进行了。(有些大的对象在Eden区无法存储时候,将直接进入老年代)
IBM公司的专门研究表明,新生代中 80% 的对象都是“朝生夕死”的。
可以使用选项”-Xmn”设置新生代最大内存大小。这个参数一般使用默认值就可以了。
上图基本反应了一个对象在堆中的变迁过程。
二 实战
1 代码
/**
* -Xms600m -Xmx600m
*
* -XX:NewRatio : 设置新生代与老年代的比例。默认值是 2.
* -XX:SurvivorRatio :设置新生代中 Eden 区与 Survivor 区的比例。默认值是 8
* -XX:-UseAdaptiveSizePolicy :关闭自适应的内存分配策略 (暂时用不到)
* -Xmn:设置新生代的空间的大小。 (一般不设置),它的优先级高于 XX:NewRatio
*/
public class EdenSurvivorTest {
public static void main(String[] args) {
System.out.println("我只是来打个酱油~");
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2 测试1——查看堆中各区的比例情况
E:\javatest1\src\main\java\jvm>jps
12112 Jps
13568
16932 Main
12440 KotlinCompileDaemon
5848 EdenSurvivorTest
5992 Launcher
E:\javatest1\src\main\java\jvm>jinfo -flag SurvivorRatio 5848
-XX:SurvivorRatio=8
E:\javatest1\src\main\java\jvm>jinfo -flag NewRatio 5848
-XX:NewRatio=2
3 测试2——查看堆中各区的比例情况
4 测试3—— -XX:SurvivorRatio 的测试
从测试2的结果看,Survivor 和 Eden 比例是6,而不是8。这是自适应的内存分配策略参数(-XX:+UseAdaptiveSizePolicy)造成的。
关闭自适应的内存分配策略参数(-XX:-UseAdaptiveSizePolicy)。
发现 Survivor 和 Eden 比例还是6,没有起作用。
只有显示设置 -Xms600m -Xmx600m -XX:SurvivorRatio=8,才起作用。