-Xss
The default value depends on the platform:
- Linux/x64 (64-bit): 1024 KB
- macOS (64-bit): 1024 KB
- Oracle Solaris/x64 (64-bit): 1024 KB
- Windows: The default value depends on virtual memory
public class Demo1 {
private static int count = 0;
public static void main(String[] args) {
method1();
}
private static void method1() {
count ++ ;
System.out.println(count);
method1();
}
}
线程 A
的计数器记录当前执行到了第三行字节码,这时候时间片用完了,CPU 切换到其它线程运行,当 CPU 再次切换到 线程 A
时,它就会从计数器得知上次执行的代码位置,继续向下运行。 @Test
public void testHeap(){
List<String> l = new ArrayList<String>();
String s = "abc";
String ss = "123";
while (true){
s+=ss;
l.add(s);
}
}
-Xms #最小堆内存
-Xmx #最大堆内存 一般最大值和最小值设置相同,不会因为内存重新分配,造成性能浪费。
GC Root对象: 包括栈帧中的局部变量、方法区中的静态变量、方法区中的常量、本地方法栈中JNI引用的对象。
第一遍标记、第二遍收集。缺点是会产生内存碎片,碎片过多,仍会使得连续空间少。
第一遍标记、第二遍整理,整理是指存活对象向一端移动来减少内存碎片,缺点是:整理过程相对效率较低。
开辟两份大小相等空间,一份空间始终空着,垃圾回收时,将存活对象拷贝进入空闲空间,优点是不会有内存碎片,没有整理过程。缺点是:占用空间多。
大部分对象存活时间短,小部分对象存活时间比较长。新生代对象一般很少存活,采用【复制算法】、老年代对象生存时间长,适合采用【标记-清除算法】或【标记-整理算法】
新生代内存不足触发的 GC 称为 Minor GC ,暂停时间很短,老年代内存不足触发的 GC 称为 Full GC 暂停时间较长,一般是新生代 GC 的几十倍,
当对象太大,伊甸园包括幸存区都存放不下时,这时候老年代的连续空间足够,此对象会直接晋升至老年代,不会发生 GC。
在幸存区历经多次 GC 还存活的对象会晋升至老年代,默认晋升的阈值是 15,,但注意如果目标 survivor 空间紧张,也不必等足 15 次,可以提前晋升。
minor GC: 在新生代进行的GC
又称新生代GC,指发生在新生代的垃圾收集动作;
因为Java对象大多是朝生夕灭,所以Minor GC非常频繁,一般回收速度也比较快;
major GC: 在老年代进行的GC
又称Major GC或老年代GC,指发生在老年代的GC;
Full GC : 同时作用于新生代和老年代
出现Full GC经常会伴随至少一次的Minor GC(不是绝对,Parallel Sacvenge收集器就可以选择设置Major GC策略);
Serial + SerialOld
1). Serial 工作在新生代的单线程收集器,采用『复制算法』,垃圾回收发生时,会暂停所有用户线程
2). SerialOld 工作在老年代的单线程收集器,采用『标记-整理算法』,垃圾回收发生时,会暂停所有用户线程(stop-the-world)
配置 :
-XX:+UseSerialGC
采用单线程执行所有的垃圾回收工作, 适用于单核CPU服务器,无法利用多核硬件的优势
1). Parallel Scavenge 工作在新生代的多线程收集器,采用『复制算法』,垃圾回收发生时,会暂停所有用户线程,它的特点是一个以吐量优先 的回收器。
2). Parallel Old 工作在老年代的多线程收集器,采用『标记-整理算法』,垃圾回收发生时,会暂停所有用户线程,也是以 吞吐量优先 的回收器。
配置
-XX:+UseParallelGC
-XX:+UseParallelOldGC
ParNew + SerialOld + CMS
1). ParNew 工作在新生代的多线程收集器,采用『复制算法』,垃圾回收发生时,会暂停所有用户线程,单核 cpu 并不能工作地比 Serial 好。
2). CMS(Concurrent Mark Sweep)用在重视响应速度,停顿时间最短的场合。工作在老年代,基于多线程和『标记-清除算法』,优点是在标记和清理的某些阶段不必暂停用户线程。
G1(Garbage-First)适用于大内存空间 , 会把整个内存区域划分为大小相等的若干区域(region),分为Eden ,Survivor ,Old ,Humongous 四种类型,G1优先回收其中垃圾最多的区域。它采用的算法是 Mark-Copy 不会产生大量内存碎片,它的优势在于可预测的停顿时间 。
配置 :
-XX:+UseG1GC
参数 | 描述 |
---|---|
-XX:+UseSerialGC | 启用串行收集器 |
-XX:+UseParallelGC | 启用并行垃圾收集器,配置了该选项,那么 -XX:+UseParallelOldGC默认启用 |
-XX:+UseParallelOldGC | FullGC 采用并行收集,默认禁用。如果设置了, -XX:+UseParallelGC则自动启用 |
-XX:+UseParNewGC | 年轻代采用并行收集器,如果设置了 -XX:+UseConcMarkSweepGC选项,自动启用 |
-XX:ParallelGCThreads | 年轻代及老年代垃圾回收使用的线程数。默认值依赖于JVM使用的CPU个数 |
-XX:+UseConcMarkSweepGC | 对于老年代,启用CMS垃圾收集器。 当并行收集器无法满足应用的延迟需求是,推荐使用CMS或G1收集器。 启用该选项后, -XX:+UseParNewGC 自动启用。 |
-XX:+UseG1GC | 启用G1收集器。 G1是服务器类型的收集器, 用于多核、大内存的机器。它在保持高吞吐量的情况下,高概率满足GC暂停时间的目标。 |
我们也可以在测试的时候,将JVM参数调整之后,将GC的信息打印出来,便于为我们进行参数调整提供依据,具体参数如下:
选项 | 描述 |
---|---|
-XX:+PrintGC | 打印每次GC的信息 |
-XX:+PrintGCApplicationConcurrentTime | 打印最后一次暂停之后所经过的时间, 即响应并发执行的时间 |
-XX:+PrintGCApplicationStoppedTime | 打印GC时应用暂停时间 |
-XX:+PrintGCDateStamps | 打印每次GC的日期戳 |
-XX:+PrintGCDetails | 打印每次GC的详细信息 |
-XX:+PrintGCTaskTimeStamps | 打印每个GC工作线程任务的时间戳 |
-XX:+PrintGCTimeStamps | 打印每次GC的时间戳 |
如果是在Tomcat中运行 , 需要在bin/catalina.sh的脚本中 , 追加如下配置 :
JAVA_OPTS="-XX:+UseConcMarkSweepGC -XX:+PrintGCDetails"
Windows
set JAVA_OPTS=-server -Xms2048m -Xmx2048m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -XX:SurvivorRatio=8