一、类加载过程
类加载:类加载器将.class字节码文件加载进Java虚拟机的内存中。
二、类加载器种类
例子:定义一个TestJDKClassLoader类。
运行结果:
分析:第一个为null(其实就是引导类加载器,引导类加载器是用C和C++写的,不在JDK中,根本不知道它的名字,类似于native方法),第二个为扩展类加载器,第三、四个为系统类加载器。
三、类加载机制
双亲委派模式的优势:
例子:自己在ClassPath下定义一个的java.lang.String类,在程序代码中调用String对象(Java中的String.class位于核心类库rt.jar中)
分析:根据双亲委派机制,系统类加载器先委派拓展类加载器,拓展类加载器再委派引导类加载器,如果在引导类加载器中能够加载到String.class,则直接返回,这样就和自己写的Sring.class没什么关系了,如果引导类加载器没加载到,则由拓展类加载器再去加 载,加载到则返回,否则再由系统类加载器加载。
提问:JVM加载jar包是否会将包里的所有类全部加载进内存?(可以在启动程序时加上参数:-verbose:class观察)
JVM对class文件是按需加载(运行期间动态加载),非一次性加载。(用到哪个类才加载哪个类)
四、JVM性能调优监控工具
jps
查看java程序进程
分析:12108是tomcat进程,18828是jps进程,8764是eclipse进程。这三个程序都是由Java开发的。
Jinfo
查看正在运行的Java应用程序的扩展参数。
查看JVM的参数:jinfo -flags [vmid]
查看Java系统参数:jinfo -sysprops [vmid]
Jstat
查看堆内存各部分的使用量,以及加载类的数量。
jstat [-命令选项] [vmid] [间隔时间/毫秒] [查询次数]
(注意:使用的是JDK1.8)
类加载统计:jstat -class [vimd]
分析:
垃圾回收统计:jstat -gc [vmid]
堆内存统计:jstat -gccapacity [vmid]
新生代垃圾回收统计:jstat -gcnew [vimd]
新生代内存统计:jstat -gcnewcapacity [vmid]
老年代垃圾回收统计:jstat -gcold [vmid]
老年代内存统计:jstat -gcoldcapacity [vmid]
元数据空间统计:jstat -gcmetacapacity [vmid]
jstat -gcutil [vmid]
Jmap(面试可能会问)
查看内存信息。
实例个数以及占用内存大小:jmap -histo [vmid]
打开log.txt,文件内容如下:
堆信息:jmap -heap [vmid]
堆内存dump:jmap -dump:format=b,file=[filename].hprof [vmid]
可以用JVisualVM命令工具导入该hprof快照文件分析内存运行时信息:jvisualvm
(这个工具里面的数据来源:其实就是来自Jinfo、Jmap、Jstack命令等)
(有些公司生产环境要求特别严格,linux环境下只能用jvm命令,不允许用可视化工具去调试诊断这些信息)
也可以设置内存溢出自动导出dump文件。(内存很大的时候,可能会导不出来)
① -XX:+HeapDumpOnOutOfMemoryError:
② -XX:HeapDumpPath=./(路径)
例子:运行一个OOMTest类,堆初始内存和最大内存设置为10M,让它尽快内存溢出。
当内存溢出时,自动导出dump快照文件(那一刻的内存运行情况),用JVisualVM打开:
Jstack(面试可能会问)
查看程序所有线程的堆栈情况:jstack [vmid]
用jstack查找死锁,见如下示例,也可以用jvisualvm查看死锁。
例子:运行一个DeadLockTest类,结果线程产生死锁现象。
用jps命令查看DeadLockTest进程id
接着执行:
结果:
用JVisualVM检测死锁:
JVisualVM除了本地连接以外,还能进行远程连接:
启动普通的jar程序JMX端口配置:
java -Dcom.sun.management.jmxremote.port=12345 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -jar foo.jar
tomcat的JMX配置:
JAVA_OPTS=-Dcom.sun.management.jmxremote.port=8999 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
JVisualVM远程连接服务器需要在远程服务器上配置host(连接ip、主机名),并且要关闭防火墙。
Jstack找出占用CPU最高的堆栈信息:
① 使用命令top -p [pid],显示你的java进程的内存情况,pid是你的java进程号,比如4977。
② 按H,获取每个内存的线程情况。
③ 找到内存和CPU占用最高的线程tid,比如4977。
④ 转为十六进制得到0x1371,此为线程id的十六进制表示。
⑤ 执行jstack 4977|grep -A 10 1371,得到线程堆栈信息中1371这个线程所在行的后面10行。
⑥ 查看对应的堆栈信息找出可能存在问题的代码。
原文:https://www.cnblogs.com/ZekiChen/p/12334150.html