深入java week1-01 字节码、内存、GC、调试工具

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"1. java字节码技术"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"1.1 什么是字节码?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 字节码(Java bytecode),是由Java编译器把Java代码转换后,可以由java虚拟机无脑执行的指令集。也是java跨平台的核心所在。Java维护者(组织)为所有主流操作系统提供了一个Java虚拟机,这些虚拟机向上可以识别java字节码,向下则适配本地环境,执行字节码里面的指令,在转换成cpu执行指令。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "},{"type":"text","marks":[{"type":"strong"}],"text":"它是程序的一种低级表示,可以运行于Java虚拟机上。将程序抽象成字节码可以保证Java程序在各种设备上的运行。计算机里面的很多事情问题都可以通过增加一个中间层来解决,很显然,字节码+JVM就是这么一个中间层,解决跨平台的问题。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Java bytecode由单字节(byte)的指令组成,理论上最左支持256个操作码(opcode)。实际上Java只是用了200个左右的操作码,还有一些操作码则保留给调试操作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"根据指令的性质,主要分为四个大类:"}]},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"栈操作指令,包括与局部变量交互的指令"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"Java虚拟机(JVM)是一个基于栈的计算机。所有的计算都发生在栈上。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"程序流程控制指令"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"程序的流程控制指令,比如,for,if,函数调用"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"对象操作指令,包括方法调用指令"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"java是一个面向对象的语言,创建一个对象,调用对象的方法。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"算数运算以及类型转换指令。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"1.2 查看字节码"}]},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"代码"}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/5d/5db039487bf6d60a9ae32ba7f6e7c631.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":2,"normalizeStart":2},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"查看字节码"}]}]}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"javac xxx.java 生成class文件"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"javap -c xxx.class 查看字节码"}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/3a/3a28f4bd6b0b2dfab606cfef7b7dacba.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 实际上,class文件里面保存的都是字节码,0到255的数字,上图展示的是助记符,方便记忆和阅读用的。aload_0,return等都有自己对应的操作码的。"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"javap -c -verbose xxx.class 查看更信息的字节码信息"}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/44/442c79ce6a3d2649eddabc6cee22edcf.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 上图中,有jdk的版本号,类的属性(public),还有常量表。代码行号表(调试的时候可以看到指令对于的行号)。"}]},{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":3,"normalizeStart":3},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"执行流程"}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/84/84388761bff510aa80b51c655886aed8.png","alt":null,"title":"","style":[{"key":"width","value":"25%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/b9/b9baf307ebf56822895b5732eba02d32.png","alt":null,"title":"","style":[{"key":"width","value":"25%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":" 执行的时候,从常量表中获取到常量值,在放到程序栈(变量表)中尽心计算。"}]},{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"2. 类加载"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2.1 类的生命周期"}]},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"加载(Loading):找class文件,并读入程序内存中"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"通过类名com.xxx.Class从各种classpath目录里面找到对应类,也可以自定义类加载器,从网络上加载类或jar包。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"验证(Verification): 验证格式,依赖"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"验证格式是否正确。版本号。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"类之间的相互引用关系。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"准备(Preparation): 静态字段,方法表"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"抽取类里面的静态字段"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"抽取类里面的方法。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"搭建类的结构(骨架)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"解析(Resolution): 符号解析为引用"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"把各种符号替换成引用。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":"初始化(Initialization): 构造器,静态变量赋值,静态代码"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"静态变量赋值"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"静态代码执行"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"然后这个类就可以创建实例了。可以被使用了。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"使用(Using): 创建类实例,并使用"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":7,"align":null,"origin":null},"content":[{"type":"text","text":"卸载(Unloading): 清除类的信息"}]}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2.2 什么时候会加载类,会初始化类"}]},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"当虚拟机启动时,初始化用户指定的主类。(main方法所在的类)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"当遇到用以新建目标类实例的new指令时,初始化new指令的目标类,就是new一个类的时候要初始化。(创建类的实例,那肯定需要类被加载了。)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"当遇到调用静态方法的指令时,初始化该静态方法所在的类。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"当遇到访问静态字段的指令时,初始化该静态字段所在的类。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":"子类的初始化会触发父类的初始化。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"如果一个接口定义了default方法,那么直接实现或间接实现该接口的类的初始化,会触发该接口的初始化。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":7,"align":null,"origin":null},"content":[{"type":"text","text":"使用反射API对某个类进行反射调用时,初始化这个类,反射调用要么是已经有实例了,要么是静态方法,都需要初始化。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"当初次调用MethodHandle实例时,初始化该MethodHandle指向的方法所在的类。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":9,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2.3 什么时候会加载类,不会初始化类"}]},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"通过子类引用父类的静态字段,只会触发父类的初始化,而不会触发子类的初始化。但子类肯定是被加载了的。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"定义对象数组,不会触发类的初始化。数组只是一个声明,实际上还没有创建对象呢。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"常量在编译期间会存入调用类的常量池中,本质上并没有直接一用定义常量的类,不会触发定义常量所在的类。比如:java字符串字面量\"xxxx\"其实就是一个String常量了。但是并不会触发String类的初始化。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"通过类名获取Class对象,不会触发类的初始化。Hello.Class不会让Hello类初始化。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":"通过Class.forName加载指定类时,如果指定参数initialize为false时,不会触发类初始化,其实这个参数是告诉虚拟机,是否需要对类进行初始化。Class.forName(\"jvm.Hello\")默认会初始化Hello类。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"通过ClassLoader默认的loadClass方法,不会触发初始化动作(类加载了,但是不初始化)"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":7,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "},{"type":"text","marks":[{"type":"size","attrs":{"size":14}},{"type":"strong"}],"text":"所谓加载类,不初始化类指的就是,会从class文件里面加载类的字节码,但是并不会执行静态字段的赋值,静态代码块的执行。"}]},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2.4 类加载器"}]},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"启动类加载器(BootstrapClassLoader)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"加载JVM启动的核心系统类"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"扩展类加载器(ExtClassLoader)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"扩展的类,也是在jdk里面自带的。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"应用类加载器(AppClassLoader)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"加载程序员写的代码,jar包。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"怎么保证类不会重复加载?"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"双亲委托:应用类加载器在加载类的时候,会先去扩展类加载器里面找类是否已被加载,如果没有就去启动类加载器找,如果还没有,则自己加载类。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"负责依赖:加载一个类的时候,还需要把这个类依赖的其它类也给加载进来。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"缓存加载:类被加载完后,会缓存起来。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"自定义类加载器"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"自定义类加载器加载出来的类是不一样的,哪怕都是从同一个class文件加载进来的类,但是实例是不能相互类型转换的。因为没有共同的上一级加载器。java中类其实也是一个对象,不同的加载器加载的类,就相当于2个类对象,虽然对象的内容是一样的,但是地址什么的就不一样了(比喻)。基于这个特性,可以加载不同版本的类,解决类兼容的问题,比如引入了一个外部工具,这个工具依赖了xxx.class 1.0.0。但是现有的代码也依赖的却是xxx.class 1.1.0这样就势必要加载2个版本的xxx.class了。那么自定义类加载器就派上用场了。"}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/4b/4bb7ed7c21fbe37e56364572ed149e0e.png","alt":null,"title":"","style":[{"key":"width","value":"50%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2.5 添加引用类的几种方式(就是发现类)"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"把类/jar放到JDK的lib/ext下,或者-Djava.ext.dirs指定类查找路径"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"java-cp/classpath或者class文件放到当前路径"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"自定义ClassLoader加载。这个就比较灵活了,可以从网络上下载一个类。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"拿到当前执行类的ClassLoader,反射调用addUrl方法添加jar或者路径。说白了,还是添加路径其他的类加载器才能找到类、jar包。(JDK9就不能用这种方法了,提供了新方法。)"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"3. JVM内存模型"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"4. JDK内置的命令行工具"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"4.1 工具功能展示"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"4.1.1 jps/jinfo"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"查看当前系统启动的java进程。就跟linux的ps命令一样,只是jps只显示java进程"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"jps -mlv :查看更详细的信息。jvm的启动参数,垃圾回收算法等。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null}}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"4.1.2 jstat"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"jstat -gc 98800 1000 20 查看进程98800的内存,和gc情况,1000表示每秒刷新一次,显示20次。s0c存活区0的容量,s0u表示存活区0使用的内存数。EC表示伊甸区的容量。OC老年区的容量。MC表示元数据区的容量。YGC表示youngGC次数。YGCT表示youngGC的总时间。FGC全量垃圾回收的册数,FGCT表示全量GC的总时间。单位都是字节。"}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/67/675b5e7016b9c15d51f1d715f1bd7842.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"jstat -gcutil 98800 1000 20: 查看各个区域内存的使用率。百分比"}]}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"4.1.3 jmap 查看更详细的jvm信息,jvm里面的所有对象,以及对象个数,使用的字节数。如果某个对象特别多。可能就是内存泄漏了。"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"jmap -histo pid"}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/7d/7da5842e69d18f5cd3bfb59966b47897.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"jmap -heap 14068 查看堆内存信息"}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/d8/d86eb8ac036c5d9da87e7669aa6b5a5e.png","alt":null,"title":"","style":[{"key":"width","value":"50%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"4.1.4 jstack"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"jstack pid:查看jvm所有线程的栈。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"4.1.5 jcmd"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"jcmd是一个比较综合的命令行工具。和上面的那些都是职责单一的。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"jcmd 14068 help :查看指定进程,支持哪些工具。"}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/50/50e16c9283be36dc0b19dcd94d0ef3c3.png","alt":null,"title":"","style":[{"key":"width","value":"50%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"jcmd pid Thread.print: 查看jvm的所有线程栈。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"4.1.6 jrunscript/jjs"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"执行js脚本命令。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"5. JDK内置图形化工具"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"说明:功能其实和命令行工具差不多,只是有窗口界面,比较方便。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"5.1 jconsole"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 图形化显示JVM内存,线程,cpu的使用情况。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/57/5793de87945aa9c44a42fc725a0bc053.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"5.2 jvisualvm"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 抽样统计功能,比jconsole更好用一点。更强大一点。可以查看一段时间(单位时间)系统的状态。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/66/66a0794b85ab7c950ce37c171ac0cd24.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"5.3 jmc"}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"死锁都能检测出来。"}]},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章