一、Trace 跟踪参数

  在Eclipse中,如何打开GC的监控日志
    选择菜单栏Run -> Run Configurations -> Java Application -> 选择自己的项目 -> 在右侧找到Arguments选项卡 -> 在VM arguments中填写参数,具体参数在下面会有说明。

    根据右侧Main的project和下面Main class确定自己监控的main方法

    在右侧找到Arguments选项卡 -> 在VM arguments中填写参数

  • -verbose:gc(打开GC的跟踪日志)

  • -XX:+printGC(打开GC的log的开关,简要日志)

    上图为我自己的一个小项目中的gc简要的日志信息 其中 9865k 表示在堆中GC之前使用了9865k的空间,2891k 表示GC之后使用2891k的空间,剩空间为19456k ,本次GC使用的时间为0.0021802 secs

  • -XX:+PrintGCDetails(打印GC的详细信息)

    上图我们以第二条为例:PSYoungGen表示新生代 GC之前为9214k,GC之后为 1016K,新生代总大小为9216k,GC所使用的时间为0.0016505 secs。而后面的信息则为上面简要信息中的内容。user 总计本次 GC 总线程所占用的总 CPU 时间 ,sys – OS 调用 or 等待系统时间,real – 应用暂停时间,如果GC 线程是 Serial Garbage Collector单线程的方式的话,  real time 等于user 和 system 时间之和.

(def new generation)新生代
(total 13824K)共有13824K空间可用,(used 11223K)有11223K被使用。
(eden space 12288k.91%)伊甸区 对象出生的地方有 12288K 的空间,有91%已经被占用
(from space 1536K,0%)s0区 1536K空间,被占用为0
(to space 1536K,0%)s0区 1536K空间,被占用为0
(tenured generation)老年代
(the space 5120K,0%)有5120K空间被占用为0
(compacting perm gen)永久代
(the space 12288k,1%)有12288K空间被占用为1%,在jdk5.0之后在串行GC下有一个永久区共享,打开共享之后一些基础的java类可用被所有的jvm共同使用,所以被占用率较小.
(ro space 10240K,44%)只读共享区间 有10240K空间 44%被占用
(rw space 12288K,52%)可读可写共享区间 有12288K空间,52%被占用

(而最后[]号中的3个值为地址值,分别表示当前内存区域的地址开始地址,当前地址,最大地址上限)

  上图为我自己获取到的jvm日志信息,永久代被删除,取而代之的是Metaspace 元数据区域,这是 java8 所做的替换。

持久代中存的内容:

  1. JVM中类的元数据在Java堆中的存储区域。
  2. Java类对应的HotSpot虚拟机中的内部表示。
  3. 类的层级信息,字段,名字。
  4. 方法的编译信息及字节码。
  5. 变量
  6. 常量池和符号解析

元空间的特点:

  1. 充分利用了Java语言规范中的好处:类及相关的元数据的生命周期与类加载器的一致。
  2. 每个加载器有专门的存储空间
  3. 只进行线性分配
  4. 不会单独回收某个类
  5. 省掉了GC扫描及压缩的时间
  6. 元空间里的对象的位置是固定的
  7. 如果GC发现某个类加载器不再存活了,会把相关的空间整个回收掉
  • -XX:+PrintGCTimeStamps(打印GC发生的时间戳)
  • -Xloggc:log/ge.log(指定GC.log的位置,以文件形式输出)
  • -XX:+PrintHeapAtGC(每一次GC后都打印出堆信息)

   Heap before GC 表示GC之前的堆信息
   Heap after GC 表示GC之后的堆信息

  • -XX:+TraceClassLoading(监控类加载,可以在程序运行时检出哪些类被加载了)

  • -XX:+PrintClassHistogram(加入此参数,在运行时不会有其他东西输出,但是在按下Ctrl+Break后可以打印出类的信息,类的直方图)

  上述4个列分别代表了(num)序号,(instances)实例数量,(bytes)总占用空间,(class name)类型
    ([B)有890617个byte数组,占用了470266000的空间
    (java.util.HashMap$Node)hashMap的结点有890643个占用21375432的空间

二、堆的分配参数

  • -Xmx(最大堆的空间)
  • -Xms(最小堆的空间)

System.out.println("系统最大使用空间:Xmx=" + Runtime.getRuntime().maxMemory()/1024.0/1024 + "M");
System.out.println("系统可用空间:free mem=" + Runtime.getRuntime().freeMemory()/1024.0/1024 + "M");
System.out.println("系统中分配到的空间:total mem=" + Runtime.getRuntime().totalMemory()/1024.0/1024 + "M");

   我们可以通过上述代码来获取系统中实际使用的空间大小。

  我们可以看到,我的系统中最大堆空间为18.0M,系统分配到的空间为9.5M,是比较接近于我们自己设置的值,系统目前可用空间为7.9M,此时系统存在可用空间。
  当我在我的系统中加入一行代码,创建一个1M的byte数组

byte []b = new byte[1024*1024*1];

  此时发现,系统可用空间整好少了1M,而总空间和系统中分配到的空间还是没变的,如果我们的系统使用的空间是小于系统分配的空间时,系统分配空间会尽可能维持在最小空间10M附近,只有系统使用的空间大于10M后,系统分配空间才会去扩展。我们在代码中创建一个10M的byte数组来看。

  此时,系统使用的空间肯定是大于10M的,所以我们的系统分配的空间已经扩展到了16M.如果我们创建一个大于20Mbyte的话就会发生OOM了,因为系统已经限制最大空间为20M。

  • -Xmn (设置新生代的大小)
  • -XX:NewRatio(设置新生代和老年代的比值,如果设置为4则表示(eden+from(或者叫s0)+to(或者叫s1)): 老年代 =1:4),即年轻代占堆的五分之一
  • -XX:SurvivorRatio(设置两个Survivor(幸存区from和to或者叫s0或者s1区)和eden区的比),8表示两个Survivor:eden=2:8,即Survivor区占年轻代的五分之一

    下面来看一个例子(jdk6)

//将jvm参数设置为-Xmx20m -Xms20m -Xmn1m -XX:+PrintGCDetails(将新生代的大小设置为1M)
byte []b = null;
for (int i = 0; i < 10; i++) {
b = new byte[1024*1024*1];
}

    上图为堆信息,没有发生过GC,新生代只有896K,1Mbyte无法分配到新生区,所以所有的数据都被分配到老年代,老年代的内存被占用的为10240K正好是byte的大小。
  我们将上述代码的新生代的内存进行扩大,调整到15M -Xmx20m -Xms20m -Xmn15m -XX:+PrintGCDetails

  我们发现修改新生代之后也没有发生GC,而是将数据全部分配到了新生代13824K,老年代却没有使用。

  我们将上述代码的新生代的内存进行减小,调整到不大不小的位置,调整到7M -Xmx20m -Xms20m -Xmn7m -XX:+PrintGCDetails

  此时发现GC被触发了2次,第一次回收了3M左右,第二次回收了4M左右,此时发现新生代被使用1139K,老年代被使用2507K,因为form to(s0 s1)区域的大小为704K,不足1M所以才GC时还是有一部分数据被放入了老年代。

  接下来,我们将幸存代的大小进行调整from:to:endn=1:1:2, -Xmx20m -Xms20m -Xmn7m XX:SurvivorRatio=2 -XX:+PrintGCDetails

  此时幸存代可以正常使用,GC发生了3次。第一次回收了1M,第二次回收了3M,第三次回收了3M,新生代占用了3M,此时新产生的数据没有进入到老年代。

   接下来,继续调整新生代和老年代的比例为1, -Xmx20m -Xms20m  -XX:NewRatio=1 XX:SurvivorRatio=2 -XX:+PrintGCDetails

  此时GC进行了2次回收第一次回收了3M,第二次回收了4M,还有3M在新生代,也没有数据进入老年代,并且GC只执行了2次,所以对于上一种配置效率就有所提高,因为GC时很消耗效率的。幸存代空间越大,对系统资源的浪费还是挺严重的,所以合理的分配幸存代,堆系统的效率也会有很大的帮助。

  接下来,继续调整幸存代的大小进行调整from:to:endn=1:1:3, -Xmx20m -Xms20m  -XX:NewRatio=1 XX:SurvivorRatio=3 -XX:+PrintGCDetails,此时,from和to的幸存区有2M,而endn区有6M

  此时GC只进行了1次,我们对幸存代的大小进行了合理的减小,这样更有利于内存的合理使用。

  • -XX:+HeapDumpOnOutOfMemoryError(将OOM时的堆信息导出到文件)
    如果系统出现OOM一般情况系统有可能会down掉,但是我们排查问题时需要场景重现是比较困难的,所以当我们输出了OOM的异常时,就可以直接查看,找出导致OOM的原因
  • -XX:+HeapDumpPath=XXXX(导出OOM堆信息文件的路径)
  • -XX:OnOutOfMemoryError(在系统出现OOM时,执行一个脚本,可以发送邮件,报警或者是重启程序)
  • -XX:PermSize(设置永久代的初始空间大小)
  • -XX:MaxParmSize(设置永久代的最大空间)

    在使用CGLIB等库的时候,可能会产生大量的类,这些类就有可能会撑爆永久区导致OOM
    我们来看下面实例:

for (int i = 0; i < 100000; i++) {
CglibBean c = new CglibBean(new HashMap<String, String>());
}

  当发生OOM时,我们发现永久区的空间已经是满了,然后发生GC时永久区的内容也无法被回收,所以导致了OOM,此时新生代只占用了2%,老难带占用了20%,而老年代使用率为99%.

总结:

  • 根据实际事情调整新生代和幸存代的大小,因为各个系统的情况都不一样,所以需要自己调试而找到一个相对较优的分配方案。
  • 官方推荐新生代占堆的3/8
  • 幸存代占新生代的1/10
  • 在OOM时,及得Dump出堆,确保可以排查现场问题
  • 在堆空间没有使用完时也有可能会产生OOM,此时有可能是永久代被撑爆。

三、栈大小的分配

栈是每一个线程都有的,他是线程私有的一块内存区域.栈中主要是由帧组成,而帧中是每个方法的局部变量表,操作数表,和指向常量池的引用和返回地址等组成。一般只有几百K,但是它的大小决定了线程的多少和调用函数的深度,而且每个线程都有独立的栈空间。

  • -Xss(设置栈空间的大小)
    下面看一个简单的例子:首先我们将栈空间设置为128K
private static int count = 0;
public static void recursion(long a, long b, long c) {
long e = 1, f = 2, g = 3, h = 4, i = 5, j = 6, k = 7, l = 8, m = 9;
count ++;
recursion(a, b, c);
} public static void main(String[] args) {
try {
recursion(1, 2, 3);
} catch (Throwable e) {
System.out.println("deep of calling = " + count);
e.printStackTrace();
}
}

  此时只执行了323次的递归。

  然后我们将栈空间扩大到256K再来看结果:

     此时递归执行竟然扩大到了1019,接近3倍,那么说明方法执行的深度由栈空间的大小所决定。

  然后我们将局部变量e之后的局部变量都清除再来看结果:

  我们发现,递归次数再次增加。此处说明方法执行的深度也由方法内局部变量表的个数所决定。

-------------------- END ---------------------

最后附上作者的微信公众号地址和博客地址

公众号:wuyouxin_gzh

Herrt灬凌夜:https://www.cnblogs.com/wuyx/

常用的JVM配置参数的更多相关文章

  1. 【java虚拟机】常用的jvm配置参数

    转自:https://www.cnblogs.com/pony1223/p/8661219.html 零.在IDE的后台打印GC日志: 既然学习JVM,阅读GC日志是处理Java虚拟机内存问题的基础技 ...

  2. 十个最常用的JVM 配置参数

    1.-Xms:初始堆大小.只要启动,就占用的堆大小. 2.-Xmx:最大堆大小.java.lang.OutOfMemoryError:Java heap这个错误可以通过配置-Xms和-Xmx参数来设置 ...

  3. 常用JVM配置参数

    常用JVM配置参数 Trace跟踪参数 堆的分配参数 栈的分配参数 Trace跟踪参数 1.打开GC的日志,如果在程序的运行过程中,系统发生了GC,就会打印相关的信息. -verbose:gc -XX ...

  4. JVM虚拟机(1)---常用JVM配置参数

    常用JVM配置参数 常用JVM配置参数主要有:Trace跟踪参数.堆的分配参数.栈的分配参数. 一.Trace跟踪参数 跟踪参数用于跟踪监控JVM,对于开发人员来讲用于JVM调优以及故障排查的. 1. ...

  5. 一文学会JVM配置参数与工具使用

    经过前面的各种分析,我们知道了关于JVM很多的知识,比如版本信息,类加载,堆,方法区,垃圾回收等,但是总觉得心里不踏实,原因是没看到实际的一些东西. 所以这在本文,咱们就好好来聊一聊关于怎么将这些内容 ...

  6. JVM 配置参数 -D,-X,-XX 的区别

    转载请注明出处: 最近在安全护网行动,需要针对服务进行不断的安全加固,如 对服务的 log4j 的安全配置进行防护,对 fastjson 的漏洞进行安全加固等,最快的防护方法就是通过在服务启动的时候, ...

  7. JVM配置参数详解

    记录一下jvm中的一些配置参数,这些肯定不全的,希望你们能留个言,补全一下,谢谢啦! -XX: MaxDirectMemorySize--->设置直接内存,不设置与Java堆内存最大值一致 -X ...

  8. 有关JVM配置参数含义

    1.参数的含义-vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M-vmargs 说明后面是VM的参数,所以后面的其实都是JV ...

  9. JVM配置参数详解(目前不够完善)

    最近看了有关虚拟机的书籍,发现有很多虚拟机配置参数不知道,特来记录一下, -XX: MaxDirectMemorySize--->设置直接内存,不设置与Java堆内存最大值一致 -XX:Perm ...

随机推荐

  1. 调试android chrome web page简明备忘

    必备工具 adb tools.android chrome 先开启手机调试模式 adb forward tcp:9919 localabstract:chrome_devtools_remote 成功 ...

  2. 在eclipse安装mybatis的插件

    1.在help中打开 2.搜索mybatipse 3:功能简介 1:要查找某一个方法        在dao接口中某一个方法中 按住 Ctrl键 鼠标指到方法名称上 选择open xml 就会自动跳转 ...

  3. C++ Boost库 uBLAS 笔记

    构造 Vector #include <boost/numeric/ublas/vector.hpp> #include <boost/numeric/ublas/io.hpp> ...

  4. [Leetcode] N-Queens 系列

    N-Queens 系列题解 题目来源: N-Queens N-Queens II N-Queens The n-queens puzzle is the problem of placing n qu ...

  5. FPGA与CPLD的概念及其区别

    一.FPGA与CPLD的基本概念 1.CPLD CPLD主要是由可编程逻辑宏单元(LMC,Logic Macro Cell)围绕中心的可编程互连矩阵单元组成,其中LMC逻辑结构较复杂,并具有复杂的I/ ...

  6. 清理oracle的用户中的日志垃圾以及修改sys用户的密码

    清理oracle的用户中的日志垃圾1.进入:/opt/oracle/product/11g/network/admin目录2.注释掉listener.ora文件中的TRACE_LEVEL_LISTEN ...

  7. vsftpd.conf 详解

    //不允许匿名访问 anonymous_enable=NO //设定本地用户可以访问.注意:主要是为虚拟宿主用户,如果该项目设定为NO那么所有虚拟用户将无法访问 local_enable=YES // ...

  8. JavaScript 去字符串空格

    JavaScript 去字符串空格 (利用正则) # str为要去除空格的字符串: # 去除所有空格: str = str.replace(/\s+/g,""); # 去除两头空格 ...

  9. StringBuilder基本用法

    //StringBuilder用法 public class StringBuilderTest { public static void main(String[] args) { StringBu ...

  10. cenos6.5安装vsftp

    1.安装 yum install vsftpd 2.配置 vi /etc/vsftpd/vsftpd.conf 检查是否如下配置 anonymous_enable=NO #禁止匿名访问 chroot_ ...