• 关于JVM案例分析(二)


    内存分析篇

    VisualVM 通过检测 JVM 中加载的类和对象信息等帮助我们分析内存使用情况,我们可以通过 VisualVM 的监视标签对应用程序进行内存分析。

    一.内存堆Heap

    首先我们来看内存堆Heap使用情况,我本机eclipse的进程在visualVM显示如下:

    随便写个小程序占用内存大的,运行一下

    程序如下:

    复制代码
    package jvisualVM;
    
    public class JavaHeapTest {
        public final static int OUTOFMEMORY = 200000000;
        
        private String oom;
    
        private int length;
        
        StringBuffer tempOOM = new StringBuffer();
    
        public JavaHeapTest(int leng) {
            this.length = leng;
           
            int i = 0;
            while (i < leng) {
                i++;
                try {
                    tempOOM.append("a");
                } catch (OutOfMemoryError e) {
                   e.printStackTrace();
                   break;
                }
            }
            this.oom = tempOOM.toString();
    
        }
    
        public String getOom() {
            return oom;
        }
    
        public int getLength() {
            return length;
        }
    
        public static void main(String[] args) {
            JavaHeapTest javaHeapTest = new JavaHeapTest(OUTOFMEMORY);
            System.out.println(javaHeapTest.getOom().length());
        }
    
    }
    复制代码

    查看VisualVM Monitor tab, 堆内存变大了

    在程序运行结束之前, 点击Heap Dump 按钮, 等待一会儿,得到dump结果,可以看到一些Summary信息

    点击Classes, 发现char[]所占用的内存是最大的

    双击它,得到如下Instances结果

     Instances是按Size由大到小排列的

    第一个就是最大的, 展开Field区域的 values

    StringBuffer类型的 全局变量 tempOOM 占用内存特别大, 注意局部变量是无法通过 堆dump来得到分析结果的。

    另外,对于“堆 dump”来说,在远程监控jvm的时候,VisualVM是没有这个功能的,只有本地监控的时候才有。

    二.永久保留区域PermGen

    其次来看下永久保留区域PermGen使用情况

    运行一段类加载的程序,代码如下:

    复制代码
    package jvisualVM;
    
    import java.io.File;
    import java.lang.reflect.Method;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.net.URLClassLoader;
    import java.util.ArrayList;
    import java.util.List;
    
    public class TestPermGen {
        
        private static List<Object> insList = new ArrayList<Object>();
    
        public static void main(String[] args) throws Exception {
    
            permLeak();
        }
    
        private static void permLeak() throws Exception {
            for (int i = 0; i < 1000; i++) {
                URL[] urls = getURLS();
                URLClassLoader urlClassloader = new URLClassLoader(urls, null);
                Class<?> logfClass = Class.forName("org.apache.commons.logging.LogFactory", true,urlClassloader);
                Method getLog = logfClass.getMethod("getLog", String.class);
                Object result = getLog.invoke(logfClass, "TestPermGen");
                insList.add(result);
                System.out.println(i + ": " + result);
            }
        }
    
        private static URL[] getURLS() throws MalformedURLException {
            File libDir = new File("C:/Users/wadexu/.m2/repository/commons-logging/commons-logging/1.1.1");
            File[] subFiles = libDir.listFiles();
            int count = subFiles.length;
            URL[] urls = new URL[count];
            for (int i = 0; i < count; i++) {
                urls[i] = subFiles[i].toURI().toURL();
            }
            return urls;
        }
    
        
    }
    复制代码

    一个类型装载之后会创建一个对应的java.lang.Class实例,这个实例本身和普通对象实例一样存储于堆中,我觉得之所以说是这是一种特殊的实例,某种程度上是因为其充当了访问PermGen区域中类型信息的代理者。

    运行一段时间后抛OutOfMemoryError了, VisualVM监控结果如下:

    结论:PermGen区域分配的堆空间过小,我们可以通过设置-XX: PermSize参数和-XX:MaxPermSize参数来解决。

  • 相关阅读:
    (转)浅析epoll-为何多路复用I/O要使用epoll
    (转)C++对象的内存布局
    (转)C++ 虚函数表解析
    VS2008文件编码格式修改
    ubuntu与windows相关配置内容
    (转)windows宿主机,ubuntu虚拟机下的上网设置(有线网络和无线网络)
    第10章 名字控制
    php 代码重用
    php 变量
    php in_array 和 str_replace
  • 原文地址:https://www.cnblogs.com/ZJOE80/p/12298893.html
Copyright © 2020-2023  润新知