网站首页被k多久恢复,机票网站建设公司好,专门卖化妆品网站建设,网站路径优化怎么做摘要#xff1a;java内存dump是jvm运行时内存的一份快照#xff0c;利用它可以分析是否存在内存浪费#xff0c;可以检查内存管理是否合理#xff0c;当发生OOM的时候#xff0c;可以找出问题的原因。那么dump文件的内容是什么样的呢#xff1f;JVM dumpjava内存dump是jv…摘要java内存dump是jvm运行时内存的一份快照利用它可以分析是否存在内存浪费可以检查内存管理是否合理当发生OOM的时候可以找出问题的原因。那么dump文件的内容是什么样的呢JVM dumpjava内存dump是jvm运行时内存的一份快照利用它可以分析是否存在内存浪费可以检查内存管理是否合理当发生OOM的时候可以找出问题的原因。那么dump文件的内容是什么样的呢我们一步一步来获取JVM dump文件获取dump文件的方式分为主动和被动i.主动方式1.利用jmap也是最常用的方式jmap -dump:[live],formatb,file2.利用jcmdjcmd GC.heap_dump3.使用VisualVM可以界面操作进行dump内存4.通过JMX的方式MBeanServer server ManagementFactory.getPlatformMBeanServer();HotSpotDiagnosticMXBean mxBean ManagementFactory.newPlatformMXBeanProxy(server, com.sun.management:typeHotSpotDiagnostic, HotSpotDiagnosticMXBean.class);mxBean.dumpHeap(filePath, live);ii.被动方式被动方式就是我们通常的OOM事件了通过设置参数-XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPathdump文件分析结构示意图结构详解dump文件是堆内存的映射由文件头和一系列内容块组成文件头由musk, 版本identifierSize, 时间4部分组成1、musk4个byte内容为J, A, V, A即JAVA2、version若干byte值有以下三种 PROFILE 1.0\0, PROFILE 1.0.1\0, PROFILE 1.0.2\03、identifierSize4个byte数字值为4或者8表示一个引用所占用的byte数4、time8个bytedump文件生成时间说明java一个类的成员变量有两种类型基本类型(8种基本类型)它们占用byte数固定不变每生成一个对象它们就需要给它们赋初始值分配空间是引用类型表示一个对象在类中只有一个引用引用只是一个数值所占用的空间大小为identifierSize被引用对象即将在堆中的另一个地方例如定义一个类public class Person {private int age;//4个byteprivate String name;//identifierSize个byteprivate double weight;//8个byte}当我们在new Person()的时候它就需要申请一个空间空间大小为 对象头大小4identifierSize8个byte对象大小的测量jdk提供一个测试对象占用内存大小的工具Instrumentation但是Instrumentation没法直接引用到需要通过agent来引用到定义一个Premain类, javac Premain.java//Premain.javapublic class Premain {public static java.lang.instrument.Instrumentation inst;public static void premain(String args, java.lang.instrument.Instrumentation inst) {Premain.inst inst;}}编写一个Manifest文件manifest.mfManifest-Version: 1.0Premain-Class: PremainCan-Redefine-Classes: trueCan-Retransform-Classes: true打包jar -cmf manifest.mf premain.jar Premain.class定义一个执行类, javac PersonTest.java//PersonTest.javapublic class PersonTest {public static void main(String[] args) throws Exception {Class clazz Class.forName(Premain);if (clazz ! null) {Person p new Person();java.lang.instrument.Instrumentation inst (java.lang.instrument.Instrumentation)clazz.getDeclaredField(inst).get(null);System.out.println(person size:[ inst.getObjectSize(p) ]B);System.out.println(class size:[ inst.getObjectSize(p.getClass()) ]B);}}}带agent执行java -javaagent:premain.jar PersonTest结果person size:[32]Bclass size:[504]B内容块每个块都是块头和块体组成块头块头由1个byte的块类型4个byte的时间time4个byte的长度表示此内容块占用byte数type类型一般有5种字符串类栈桢栈及dump块字符串由identifierSize个byte的字符串id后面是(length-identifierSize)个byte的字符串内容(后续对字符串是直接引用的这里面的id)类由4个byte的类序列(在栈桢中使用)identifierSize个byte的类id(解析类的时候用到)4个byte的序列id(暂未使用),identifierSize个byte的类名id栈桢由identifierSize个byte的桢id,identifierSize个byte的方法名id,identifierSize个byte的方法标识ididentifierSize个byte的类文件名id,4个byte的类序列4个byte的行号栈由4个byte的栈序号4个byte的线程序号4个byte的桢数量后面就是若干个identifierSize个byte的桢iddump块就是所有对象的内容了每个对象由1个byte的子类型和对象内容结成子类型有6种gc root, 线程对象类对象基本类型数组对象数组gc rootgc root有4种结构8种类型identifierSize个byte的对象id类型有SYSTEM_CLASS,BUSY_MONITOR, 及未UNKNOWNidentifierSize个byte的对象id4个byte的线程序列号类型有NATIVE_STACKTHREAD_BLOCKidentifierSize个byte的对象id4个byte的线程序列号4个byte的栈桢深度类型有JAVA_LOCALNATIVE_LOCALidentifierSize个byte的对象ididentifierSize个byte的global refId(暂未使用)类型有NATIVE_STATICgc root示意图gc root为垃圾收集追溯的源头每个gc root都指向一个初始对象无法追溯的对象是要被回收掉的系统类只有classLoader为null的类才是gc root每个类都是一个gc root线程栈线程中方法参数局部变量都是gc root每个对象都是一个gc root系统保留对象每个对象都是一个gc root类对象1、基本信息identifierSize个byte的类对象id4个byte的栈序列号identifierSize个byte的父类对象ididentifierSize个byte的classLoader对象ididentifierSize个byte的Signer对象ididentifierSize个byte的protection domain对象ididentifierSize个byte的保留id1和id2,4个byte的类实例对象大小2个byte的常量个数后面是每个常量的,2个byte的下标1个byte的常量类型和若干个byte的内容内容根据类型来决定(boolean/byte为1个byte, char/short为2个bytefloat/int为4个byte, double/long为8个byte引用类型为identifierSize个byte)2个byte的静态变量个数后面是每个静态变量的identifierSize个byte的变量名id, 1个byte的变量类型和若干个byte的内容内容根据类型来决定(见类对象基本信息的第9条)2个byte的成员变量个数后面是每个成员变量的identifierSize个byte的变量名id1个byte的变量类型2、说明(1)类里面的常量很多地方都没有用上所以常量个数一般为0(2)类的静态变量的名称类型及值是放在类对象里面的成员变量的名称和类型也是放在类对象里面的但是实例的值是放在实例对象里面的实例对象1、基本信息identifierSize个byte的实例对象id4个byte的栈序列号identifierSize个byte的类id4个byte的占用字节数实例的变量的值2、说明实例的值为实例对象的成员变量值顺序为当前类的变量值顺序为类对象基本信息中第11条中的顺序然后是父类的变量值变量的值基本类型都有默认值引用类型默认值为0占用字节数(见类对象基本信息的第9条)基本类型数组1、基本信息identifierSize个byte的数组对象id4个byte的栈序列号4个byte的数组长度1个byte的元素类型元素的值列表2、说明元素的值(见类对象基本信息的第9条)对象数组1、基本信息identifierSize个byte的数组对象id4个byte的栈序列号4个byte的数组长度identifierSize个byte的元素类id元素的值列表内存分配当一个线程启动的时候进程会去系统内存生成一个线程栈每当发生一次方法调用就会向栈中压入一个栈桢当方法调用完之后栈桢会退出在运行过程中如果有对象的new操作的时候进程会去堆区申请一块内存关于运行时内存的详细情况可以查找相关的资料内存回收规则如果一个对象不能骑过gc root引用可达那么这个对象就可能要被回收对象回收规则包括实例属性被实例引用只有当实例被回收了实例属性才能被回收(只针对强引用)类对象被实例引用只有当一个类的所有实例都被回收了类才能被回收类对象的父类classLoader对象signer对象, protection domain对象被类引用只有当类被回收了这些才能被回收局部变量(线程栈中)的作用域为一个大括号public void test(){Object a new Object();//obj 1Object b new Object();//obj 2{Object c new Object();//obj 3a null;//obj 1可以被回收了}//obj 3可以回收了}//obj 2可以被回收了分析工具简介分析dump文件我们可以用jdk里面提供的jhat工具执行jhat xxx.dumpjhat加载解析xxx.dump文件并开启一个简易的web服务默认端口为7000可以通过浏览器查看内存中的一些统计信息一般使用方法会列出一些功能包括package下面各个类的概览及各个功能导航2、点击页面的堆内存统计有一个表格对象类型实例个数实例所占用内存大小哪种类型的对象占用了内存最多一目了然3、点击其中认为内存消耗太多的类名查看类详情主要展现该类下面各个实例的大小以及一些链接导航4、点击references summary by type如果某种类型的对象太多那么有可能是引用它的那个类的对象太多基本上一些简单页面的查询结合原代码就可以初步定位内存泄漏的地方综上dump文件结构还是比较简单的这对于分析线程的执行情况非常有用也是每一个Java程序员必须掌握的高级技能之一你学会了吗