• jvm 内存,线程,gc分析


    1.查看 gc的次数,和各个垃圾回收区域的内存比例  jstat 

    jstat -gcutil pid interval(ms) 例子:jstat -gcutil 332 1000

    参数说明如下:
    S0: 新生代中Survivor space 0区已使用空间的百分比

    S1: 新生代中Survivor space 1区已使用空间的百分比
    E: 新生代已使用空间的百分比
    O: 老年代已使用空间的百分比
    P: 永久带已使用空间的百分比


    YGC: 从应用程序启动到当前,发生Yang GC 的次数

    YGCT: 从应用程序启动到当前,Yang GC所用的时间【单位秒】
    FGC: 从应用程序启动到当前,发生Full GC的次数
    FGCT: 从应用程序启动到当前,Full GC所用的时间
    GCT: 从应用程序启动到当前,用于垃圾回收的总时间【单位秒】

    2.内存分析 jmap

     2.1 生成堆栈文件

      -dump堆到文件,format指定输出格式,live指明是活着的对象,file指定文件名

      jmap -dump:live,format=b,file=/data/dump.hprof 21275

     2.2 查看jvm 当前配置

       jmap -heap 21275

     2.3 打印当前内存中对象的数量排序

           jmap -histo:live 21275 | more

    
    

    3.线程分析  jstack

      jstack [option] PID

    -F : 当正常输出请求不被响应时,强制输出线程堆栈 
    -l : 除堆栈外,显示关于锁的附加信息 
    -m : 如果调用到本地方法的话,可以显示C/C++的堆栈

    4.生成的服务器,一般按下面进行配置。

    8G内存机器:

    • JAVA_OPTS="-Djava.awt.headless=true -server -Xms5000m -Xmx5000m -Xmn2500m -=256M -XX:MaxPermSize=512M -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=60 -XX:+UseParNewGC -verbose:gc -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintGCTimeStamps -Xloggc:/bankapp/tomcat/logs/gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/bankapp/tomcat/logs/heapdump"

    4G内存机器:

    • JAVA_OPTS="-Djava.awt.headless=true -server -Xms2500m -Xmx2500m -Xmn1000m -XX:PermSize=256M -XX:MaxPermSize=512M -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=60 -XX:+UseParNewGC -verbose:gc -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintGCTimeStamps -Xloggc:/bankapp/tomcat/logs/gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/bankapp/tomcat/logs/heapdump" 

    注意:jdk1.8的元数据区替代了之前的持久代,而且 元数据区占用linux的内存,不占用jvm内存,这时,如果发现linux内存持续飙高,请注意元数据区。

      另一个jdk1.8的jvm内存,会缓慢增加,而不会,jvm一启动就会占用 Xms Xmx指定的值,慢慢增加到  Xms Xmx指定的值。

    -XX:MinMetaspaceFreeRatio=30 -XX:MaxMetaspaceFreeRatio=60 ?这两个没发现用处。
    -XX:MetaspaceSize=5M -XX:MaxMetaspaceSize=512M  

    5.内存泄漏模拟(jdk1.8)

    5.1堆内存溢出

    好处,生成的对象大约占用1M,最后滚局i的值,可以算出内存的大小。

    import java.util.ArrayList;
    import java.util.List;
     
    public class HeapOomMock {
        public static void main(String[] args) {
            List<byte[]> list = new ArrayList<byte[]>();
            int i = 0;
            boolean flag = true;
            while (flag){
                try {
                    i++;
                    list.add(new byte[1024 * 1024]);//每次增加一个1M大小的数组对象
                }catch (Throwable e){
                    e.printStackTrace();
                    flag = false;
                    System.out.println("count="+i);//记录运行的次数
                }
            }
        }
    }

    5.1栈溢出

    public class StackSOFTest {
    
        int depth = 0;
    
        public void sofMethod(){
            depth ++ ;
            sofMethod();
        }
    
        public static void main(String[] args) {
            StackSOFTest test = null;
            try {
                test = new StackSOFTest();
                test.sofMethod();
            } finally {
                System.out.println("递归次数:"+test.depth);
            }
        }
    }

    5.1元数据区溢出(或者是持久代溢出)

     问题:通过jvisualvm 查看内存gc时,发现元数据区的类载fullgc时没有被卸载?如果有人知道,请多多指教

    import java.lang.reflect.Method;
    
    import org.springframework.cglib.proxy.CallbackFilter;
    import org.springframework.cglib.proxy.Dispatcher;
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;  
    
    public class OOMTest {  
      
        public static void main(String[] args) {  
            System.out.println("Let us do it now.....");  
            for(int i=0;i<100000;i++){  
               Enhancer enhancer = new Enhancer();  
               enhancer.setSuperclass(TestService.class);  
               enhancer.setCallbackTypes(new Class[] {  
                        Dispatcher.class, MethodInterceptor.class });  
               enhancer.setCallbackFilter(new CallbackFilter() {  
                    public int accept(Method method) {  
                        return 1;  
                    }  
                });  
               Class clazz = enhancer.createClass();  
               System.out.println("Time:" + System.currentTimeMillis());   
            }  
        }  
    }  

    5.jvisualvm 

    5.1 jvsiualvm      local java applications cannot be monitored

    echo %TMP%

    查看tmp下面的hsperfdata_username

    我解决的方法是 把username全部大写。

    5.2 单独jvisualvm 安装

    ${jdk}/bin/jvisualvm
    本地jdk中的jvisualvm启动报错

    无法连接 Java VisualVM 插件中心
    1
    解决方式
    舍弃jdk自带jvisualvm,下载独立的。
    http://visualvm.github.io/releases.html
    根据jdk版本选择

    ${jvisualvm}/etc/visualvm.conf更改被注释的visualvm_jdkhome="..."为本机jdk绝对路径

    启动jvisualvm

    工具->插件->设置->插件中心->编辑url
    https://visualvm.github.io/pluginscenters.html
    根据版本选择.gz放到上文url中

  • 相关阅读:
    PHP
    PHP
    密码修改机制
    PHP
    PHP
    PHP
    PHP
    Java并发编程:进程和线程的由来(转)
    Java获取文件大小的正确方法(转)
    J2EE开发中常用的缓存策略
  • 原文地址:https://www.cnblogs.com/z-test/p/10196819.html
Copyright © 2020-2023  润新知