1.打印和查找上一篇讲到 的 参数

windows下可以使用findstr (代替grep)

Java HotSpot常用选项(续)_垃圾回收

2.Java代码获取JVM相关参数

可以借助java.lang.management.*

public class JVMParameterTest {
@Test
public void TestGetResource(){
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
MemoryUsage usage = memoryMXBean.getHeapMemoryUsage();

List myList = new ArrayList();
myList.add("Heap Memory setting:");
myList.add(usage.getInit());
myList.add(usage.getMax());
myList.add(usage.getUsed());
myList.add("Full info:");
myList.add("Heap info:");
myList.add(memoryMXBean.getHeapMemoryUsage());
myList.add("NonHeap info:");
myList.add(memoryMXBean.getNonHeapMemoryUsage());

List<String> inputArgs = ManagementFactory.getRuntimeMXBean().getInputArguments();
System.out.println("=============java options==============");
inputArgs.forEach(item->System.out.println(item));

myList.add("==========Java System Status=========");
myList.add((int) Runtime.getRuntime().totalMemory());
myList.add((int) Runtime.getRuntime().freeMemory());
myList.add((int) Runtime.getRuntime().maxMemory());

myList.add("==========Java OS MXBean=========");
OperatingSystemMXBean osm =(OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();

myList.add(osm.getFreePhysicalMemorySize());
myList.add(osm.getFreeSwapSpaceSize());
myList.add(osm.getTotalPhysicalMemorySize());
myList.add("osm.getAuth():"+osm.getArch());
myList.add("som.getAvailableProcessors():"+osm.getAvailableProcessors());
myList.add("som.getName():"+osm.getName());
myList.add("som.getCommittedVirtualMeSize():"+osm.getCommittedVirtualMemorySize());
myList.add("som.getProcessCpuTime():"+osm.getProcessCpuTime());
myList.add("osm.getVersion():"+osm.getVersion());
myList.add("====================获取虚拟机的内存使用情况===============");

MemoryMXBean mm = (MemoryMXBean) ManagementFactory.getMemoryMXBean();

myList.add("mm.getHeapMemoryUsage():"+mm.getHeapMemoryUsage());
myList.add("mm.getNonHeapMemoryUsage():"+mm.getNonHeapMemoryUsage());

myList.add("====================获取各个线程 状态===============");

ThreadMXBean tm = (ThreadMXBean) ManagementFactory.getThreadMXBean();
myList.add("tm.getThreadCount():"+tm.getThreadCount());
myList.add("tm.getPeakThreadCount():"+tm.getPeakThreadCount());
myList.add("tm.getCurrentThreadCpuTime():"+tm.getCurrentThreadCpuTime());
myList.add("tm.getDaemonThreadCount():"+tm.getDaemonThreadCount());
myList.add("tm.getCurrentThreadUserTime():"+tm.getCurrentThreadUserTime());
myList.add("====================获取编译器情况===============");
CompilationMXBean gm = (CompilationMXBean) ManagementFactory.getCompilationMXBean();
myList.add("gm.getName():"+gm.getName());
myList.add("gm.getTotalCompilationTime():"+gm.getTotalCompilationTime());
myList.add("==================== 获取 GC次数以及花费时间之类的信息 ===============");

List<GarbageCollectorMXBean> gcmList= ManagementFactory.getGarbageCollectorMXBeans();
gcmList.forEach(item->{
myList.add("getName:"+item.getName());
myList.add("getMemoryPoolNames:"+item.getMemoryPoolNames());
});

myList.add("==================== 获取 运行时 信息 ===============");
RuntimeMXBean rmb = (RuntimeMXBean) ManagementFactory.getRuntimeMXBean();
myList.add("getClassPath():"+rmb.getClassPath());
myList.add("getLibraryPath():"+rmb.getLibraryPath());
myList.add("getVmVersion():"+rmb.getVmVersion());




myList.forEach(item->System.out.println(item));

}

}

执行后的结果如下:

Java HotSpot常用选项(续)_垃圾回收_02

运行时的信息太多与复杂和多,不适合展示


3.HotSpot选项之垃圾回收收集器

3-1 吞吐量优先收集器的相关选项

有两个衡量收集器的指标:吞吐量和停顿时间

吞吐量:执行用户代码的实践占据总时间的比例

总时间:执行用户代码的时间和垃圾回收的时间

实践:二者不可同时进行,垃圾回收的时候,执行用户代码的线程必须暂停,这就导致程序暂时失去响应。

停顿时间:衡量垃圾回收时候造成的用户线程暂停的时间

实践:两个指标是有一定矛盾的,所以只能优先选择其中一个目标

实践:HotSpot中,侧重于吞吐量的是Parallel Scavenge和Parallel Old

Parallel Scavenge和Parallel Old 相关参数:

-XX:+UseParallelOldGC

表示年轻代和老年代都使用并行回收器

-XX:ParallelGCThreads=n

表示配置多少个线程来回收垃圾

实践:默认值,cpu小于8个,就是处理器个数;大于8,就是3+(5/8)*N

实践:也可以根据程序的需要去设置这个值,比如你的机器有16核,上面有4个Java程序,那么设置将这个值设置为4比较合理,因为JVM不会去探测同一机器上有多少个Java程序

-XX:UseAdaptiveSizePolicy

表示是否开启自适应策略

实践:打开后,JVM会自动调节JVM的年轻代大小,Eden,S的比例等参数

用户只需要设置期望的吞吐量(-XX:GCTimeRatio)和期望的停顿时间(

-XX:MaxGCPauseMillis),其余交给JVM去优化

注:如果CPU只有一个核,那么就不要开启并行回收器;很简单多线程会抢夺CPU资源;可以采用串行回收器(-XX:UseSerialGC)

3-2 CMS 垃圾回收收集器

ConcurrentMarkandSweep

相对于上面两个关注吞吐量,CMS侧重于系统停顿时间。

思路:

把收集器分成了不同的阶段,其中某些阶段是可以二者并行,这样就可以减少整体的系统停顿时间。

细节:

阶段划分

--初始标记   initial mark

--并发标记   concurrent merk

--重新标记   remark

--并发清理   concurrent clean

--并发重置   concurrent reset

缺点:

1.思路上可以知道,它是标记-清除收集器,运行一段时间,必然会产生内存碎片,从而导致无法找到连续空间来分配较大对象

2.运行过程中,占用一些内存,同时系统也在运行,如果系统产生对象的速度远远大于CMS清理的速度,就会导致CMS运行失败

以上两个发生其中一个,JVM就会促发FullGC,导致停顿时间更长

ConcurrentMarkandSweep相关选项

-XX:+UseConcMarkSweepGC

表示老年代开启CMS收集器,而年轻代默认使用并行收集器

-XX:ConcGCThreads

指定用多少个线程来执行CMS的并发阶段

-XX:CMSInitiatingOccupancyFraction

指老年代用掉多少内存后  开始进行垃圾回收

区别​:吞吐量优先的收集器是在老生代内存用尽了才会收集

特点:CMS不可以,因为吞吐量优先的收集器会停止所有用户线程,所以不会产生新的对象,而CMS运行的时候,用户线程还是会产生新的对象,所以不能等到用光的时候才进行

实践:-XX:CMSInitiatingOccupancyFraction=75表示老生代用掉75%后开始回收垃圾。默认值是68。 

-XX:ExplictGCInvokesConcurrent

实践:关闭时候,调用System.GC()会执行Full GC从而导致用户线程被暂停

开启的时候,显示触发GC的时候,还是使用CMS

-XX:DisableExplictGC

就是禁止显式调用GC

4:GC日志相关的选项

-XX:+PrintGC

等同于 -verbose:gc

表示开启简化的GC日志

分为GC部分和Full GC部分(容量变化和花费时间)

-XX:+PrintGCDetail:

在垃圾回收的时候打印内存回收日志,并且在进程退出时候输出当前内存各区域的分布情况

-XX:PrintGCTimeStamps 

打印GC发生时候相对于JVM启动的时间间隔

-XX:+PrintGCDateStamps

打印GC发生的具体时间

例子:打开两个选项后

20**-**-**T**:52:**.613-0800: 3.***: [GC 1397*6K->583*9K(506***K), 0.14***00 secs]

-Xloggc:<file>

表示把GC写入文件

-XX:+PrintHeapAtGC

每一次GC的前后,都打印堆内存的情况

-XX:+TraceClassLoading

监控类的加载

-XX:+PrintGCApplicationStoppedTime

打印GC时线程的停顿时间


注意:这些和日志相关的选项是可以在JVM启动后,再开启;

这个时候需要使用jdk自带的命令 jinfo 去设置(jps)

也就是再有问题的时候开启GC日志


这样,两篇就说清楚了常见选项。

此处感谢博客园的狂风骤起