类加载机制与JVM调优命令
一、类加载过程
类加载:类加载器将.class字节码文件加载进Java虚拟机的内存中。
- 加载:在硬盘上查找并通过IO读入字节码文件
- 连接:执行校验、准备、解析(可选)步骤
- 校验:校验字节码文件的正确性
- 准备:给类的静态变量分配内存,并赋予默认值
- 解析:类加载器载入类所引用的其他所有类
- 初始化:对类的静态变量初始化为指定的值,执行静态代码块
二、类加载器种类
- 引导类加载器:负责加载JRE的核心类库,如JRE目标下的rt.jar、charsets.jar等
- 扩展类加载器:负责加载JRE扩展目录ext中的jar类包
- 系统类加载器:负责加载ClassPath路径下的类包
- 自定义类加载器:负责加载用户自定义路径下的类包
例子:定义一个TestJDKClassLoader类。
运行结果:
分析:第一个为null(其实就是引导类加载器,引导类加载器是用C和C++写的,不在JDK中,根本不知道它的名字,类似于native方法),第二个为扩展类加载器,第三、四个为系统类加载器。
三、类加载机制
- 全盘负责委托机制:当一个ClassLoader加载一个类时,除非显示的使用另一个ClassLoader,否则该类所依赖和引用的类也由这个ClassLoader载入
- 双亲委派机制:指先委托父类加载器寻找目标类,在找不到的情况下再从自己的路径中查找并载入目标类
双亲委派模式的优势:
- 沙箱安全机制:自己写的String.class类不会被加载,这样可以防止核心API库被随意篡改
- 避免类的重复加载:当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次
例子:自己在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]
分析:
- Loaded:加载class的数量
- Bytes:所占用空间大小
- Unloaded:未加载数量
- Bytes:未加载占用空间
- Time:消耗时间
垃圾回收统计:jstat -gc [vmid]
- S0C:第一个幸存区的大小
- S1C:第二个幸存区的大小
- S0U:第一个幸存区的使用大小
- S1U:第二个幸存区的使用大小
- EC:伊甸园区的大小
- EU:伊甸园区的使用大小
- OC:老年代的大小
- OU:老年代的使用大小
- MC:方法区的大小(元数据区)
- MU: 方法区的使用大小
- CCSC:压缩类空间的大小
- CCSU:压缩类空间的使用大小
- YGC:年轻代垃圾回收次数
- YGCT:年轻代垃圾回收消耗时间
- FGC:老年代垃圾回收次数
- FGCT:老年代垃圾回收消耗时间
- GCT:垃圾回收消耗总时间
堆内存统计:jstat -gccapacity [vmid]
- NGCMN:新生代最小容量
- NGCMX:新生代最大容量
- NGC:当前新生代容量
- S0C:第一个幸存区大小
- S1C:第二个幸存区大小
- EC:伊甸园区的大小
- OGCMN:老年代最小容量
- OGCMX:老年代最大容量
- OGC:当前老年代大小
- OC:当前老年代大小
- MCMN:最小元数据容量
- MCMX:最大元数据容量
- MC:当前元数据空间大小
- CCSMN:最小压缩类空间大小
- CCSMX:最大压缩类空间大小
- CCSC:当前压缩类空间大小
- YGC:新生代GC次数
- FGC: 老年代GC次数
新生代垃圾回收统计:jstat -gcnew [vimd]
- S0C:第一个幸存区的大小
- S1C:第二个幸存区的大小
- S0U:第一个幸存区的使用大小
- S1U:第二个幸存区的使用大小
- TT:对象在新生代存活的次数
- MTT:对象在新生代存活的最大次数
- DSS:期望的幸存区大小
- EC:伊甸园区的大小
- EU:伊甸园区的使用大小
- YGC:新生代垃圾回收次数
- YGCT:新生代垃圾回收消耗时间
新生代内存统计:jstat -gcnewcapacity [vmid]
- NGCMN:新生代最小容量
- NGCMX:新生代最大容量
- NGC:当前新生代容量
- S0CMX:最大幸存1区大小
- S0C:当前幸存1区大小
- S1CMX:最大幸存2区大小
- S1C:当前幸存2区大小
- ECMX:最大伊甸园区大小
- EC:当前伊甸园区大小
- YGC:新生代垃圾回收次数
- FGC: 老年代垃圾回收次数
老年代垃圾回收统计:jstat -gcold [vmid]
- MC:方法区大小
- MU:方法区使用大小
- CCSC:压缩类空间大小
- CCSU:压缩类空间使用大小
- OC:老年代大小
- OU:老年代使用大小
- YGC:新生代垃圾回收次数
- FGC:老年代垃圾回收次数
- FGCT:老年代垃圾回收消耗时间
- GCT:垃圾回收消耗总时间
老年代内存统计:jstat -gcoldcapacity [vmid]
- OGCMN:老年代最小容量
- OGCMX:老年代最大容量
- OGC:当前老年代大小
- OC:老年代大小
- YGC:新生代垃圾回收次数
- FGC:老年代垃圾回收次数
- FGCT:老年代垃圾回收消耗时间
- GCT:垃圾回收消耗总时间
元数据空间统计:jstat -gcmetacapacity [vmid]
- MCMN:最小元数据容量
- MCMX:最大元数据容量
- MC:当前元数据空间大小
- CCSMN:最小压缩类空间大小
- CCSMX:最大压缩类空间大小
- CCSC:当前压缩类空间大小
- YGC:新生代垃圾回收次数
- FGC:老年代垃圾回收次数
- FGCT:老年代垃圾回收消耗时间
- GCT:垃圾回收消耗总时间
jstat -gcutil [vmid]
- S0:幸存1区当前使用比例
- S1:幸存2区当前使用比例
- E:伊甸园区使用比例
- O:老年代使用比例
- M:元数据区使用比例
- CCS:压缩使用比例
- YGC:新生代垃圾回收次数
- YGCT:新生代垃圾回收消耗时间
- FGC:老年代垃圾回收次数
- FGCT:老年代垃圾回收消耗时间
- GCT: 垃圾回收消耗总时间
Jmap(面试可能会问)
查看内存信息。
实例个数以及占用内存大小:jmap -histo [vmid]
打开log.txt,文件内容如下:
- num:序号
- instances:实例数量
- bytes:占用空间大小
- class name: 类名称
堆信息: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行。
⑥ 查看对应的堆栈信息找出可能存在问题的代码。
类加载机制与JVM调优命令的更多相关文章
- jvm系列(四):jvm调优-命令大全(jps jstat jmap jhat jstack jinfo)
文章同步发布于github博客地址,阅读效果更佳,欢迎品尝 运用jvm自带的命令可以方便的在生产监控和打印堆栈的日志信息帮忙我们来定位问题!虽然jvm调优成熟的工具已经有很多:jconsole.大名鼎 ...
- [转]jvm调优-命令大全(jps jstat jmap jhat jstack jinfo)
运用jvm自带的命令可以方便的在生产监控和打印堆栈的日志信息帮忙我们来定位问题!虽然jvm调优成熟的工具已经有很多:jconsole.大名鼎鼎的VisualVM,IBM的Memory Analyzer ...
- Java虚拟机(五):JVM调优命令
运用jvm自带的命令可以方便的在生产监控和打印堆栈的日志信息帮忙我们来定位问题!虽然jvm调优成熟的工具已经有很多:jconsole.大名鼎鼎的VisualVM,IBM的Memory Analyzer ...
- jvm系列(四):jvm调优-命令篇
运用jvm自带的命令可以方便的在生产监控和打印堆栈的日志信息帮忙我们来定位问题!虽然jvm调优成熟的工具已经有很多:jconsole.大名鼎鼎的VisualVM,IBM的Memory Analyzer ...
- JVM调优 — 命令大全(jps jstat jmap jhat jstack jinfo)(转)
运用jvm自带的命令可以方便的在生产监控和打印堆栈的日志信息帮忙我们来定位问题!虽然jvm调优成熟的工具已经有很多:jconsole.大名鼎鼎的VisualVM,IBM的Memory Analyzer ...
- jvm调优-命令大全(jps jstat jmap jhat jstack jinfo)
现实企业级Java开发中,有时候我们会碰到下面这些问题: OutOfMemoryError,内存不足 内存泄露 线程死锁 锁争用(Lock Contention) Java进程消耗CPU过高 运用jv ...
- JVM调优命令-jmap
jmap JVM Memory Map命令用于生成heap dump文件,如果不使用这个命令,还可以使用-XX:+HeapDumpOnOutOfMemoryError参数来让虚拟机出现OOM的时候自动 ...
- jvm调优命令
JDK监控和故障jps,jstat,jmap,jhat,jstack.jinfo jps ,JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程. jstat ...
- JVM调优命令-jstat
JVM Statistics Monitoring Tool,是用于监视虚拟机运行时状态信息的命令,它可以显示出虚拟机进程中的类装载.内存.垃圾收集.JIT编译等运行数据.[性能分析] 命令格式 1 ...
随机推荐
- 使用Razor表达式 举数组和集合 精通ASP-NET-MVC-5-弗瑞曼
- 将DataTable数据转换成List泛型数据
这里有一个实体类: public class Menuss { public int Id { get; set; } public string Te ...
- 优雅写Java之三(IO与文本解析)
一.资源相关 二.路径与文件 读文件: String fileName = "str.txt"; Files.lines(Paths.get(fileName), Standard ...
- 详细步骤:手动添加bits/stdc++.h到vs2017
本机环境:win10系统 64位 vs2017 最近码代码时偶然发现了bits/stdc++.h这个头文件(万能头文件),基本上所有的代码只要用了这个头文件就不再写其他头文件了. 看到它就仿佛开启了新 ...
- 学习记录(Python列表)
列表(List)是Python语言中最通用的序列数据结构之一,列表是一个没有固定长度的,用来表示任意类型对象的位置相关的有序集合.列表中的数据项不需要具有相同的数据类型 列表的基本操作: 1.创建列表 ...
- C++:析构函数的调用时机
结论:只有当类的某个实例化对象的构造函数执行完毕,而且当该对象退出作用域时,才会执行析构函数. 如果在执行构造函数的过程中抛出了异常,就不会调用析构函数 上测试代码: class Test { pub ...
- python学习(6)选择排序算法简单代码
选择排序的基本思想是:每一趟在n-i+1(i=1,2,…n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录.基于此思想的算法主要有简单选择排序.树型选择排序和堆排序.[1] 简单选择排序的基 ...
- Burpsuite Pro 2020.1最新破解版
简介 Burp Suite 是用于攻击web 应用程序的集成平台,包含了许多工具.Burp Suite为这些工具设计了许多接口,以加快攻击应用程序的过程.所有工具都共享一个请求,并能处理对应的HTTP ...
- 《Python编程:从入门到实践》分享下载
书籍信息 书名:<Python编程:从入门到实践> 原作名:Python Crash Course 作者: [美] 埃里克·马瑟斯 豆瓣评分:9.1分(2534人评价) 内容简介 本书是一 ...
- 介绍求解AX=b:可解性与解的结构
前面用高斯消元法或矩阵LU分解求解线性方程组的解,主要是针对有唯一解(矩阵A可逆)的情况,下面进一步介绍线性方程组有多个解的情况下,解的求解.