1.命令行
1.jps
查看正在运行的java进程
jps -l 输出应用程序主类的全类名
jps -v 列出虚拟机进程启动时的JVM参数
jps -l> a.txt 将内容输入到a.txt文件
2.jstat
查看JVM统计信息
jstat -gc 进程号 查看进程号的JVM信息,包括新生代,老年代,方法区这些空间的大小,和GC次数、时间等。(只输出一次)
jstat -gc 进程号 时间间隔(ms) 每隔多少毫秒输出一次进程信息
jstat -gc 进程号 时间间隔(ms) 总行数 每隔多少毫秒输出一次进程信息,一共输出多少次
jstat -gc -h3 -t 进程号 时间间隔(ms) 总行数 每隔多少毫秒输出一次进程信息,一共输出多少次,并且每3次就打印表头(-h3),打印时间(-t)
3.jinfo
实时查看和修改JVM配置参数
jinfo -flags 进程号 查看曾经赋过值的一些参数
jinfo -flag 参数名称 进程号 查看某个java进程的具体参数信息,比如:jinfo -flags MaxHeapSize 13892
jinfo -flag [+|-]参数名称 进程id 修改boolean类型的参数
jinfo -flag 参数名称=参数值 进程id 修改非boolean类型的参数
4.jmap
导出内存映像文件&内存使用情况
jmap -heap 进程号 打印heap的概要信息,GC使用的算法,heap(堆)的配置及JVM堆内存的使用情况.
jmap -histo:live 进程号 -histo[:live] 打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量.
jmap -finalizerinfo 进程号 打印正等候回收的对象的信息
jmap -dump:live,format=b,file=aa.txt 进程号 使用hprof二进制形式,输出jvm的heap内容到文件,live子选项是可选的,假如指定live选项,那么只输出活的对象到文件。
2.界面诊断工具
1.jconse
启动:在jdk安装目录中找到jconsole.exe,双击该可执行文件就可以;或者打开DOS窗口,直接输入jconsole就可以了。
连接方式:1.本地连接和远程连接,远程连接需要在环境变量中设置mx.remote.credentials来指定用户名和密码,从而进行授权。
用途:查看内存信息,根据线程监测死锁,加载的类的总数,VM概要等信息。
2.Visual VM
在jdk安装目录中找到jvisualvm.exe,然后双击执行即可.
打开DOS窗口,输入jvisualvm就可以打开该软件
3.JProfiler
付费
4.Arthas
阿里巴巴开源性能分析工具,可以在图形界面上看到各维度的性能数据
3.内存泄漏
1.内存泄漏的理解
可达性分析算法判断对象是否还被引用,但如果对象被引用,但程序又用不到,GC又不能回收他们就会造成内存泄漏。
内存泄漏与内存溢出的区别:泄漏是申请了内存用完了不释放,溢出是申请内存时没有足够的内存使用。可见内存泄漏与溢出的关系是:内存
泄漏的增多会导致内存溢出。
2.内存泄漏的情况
1.静态集合类
如HasMap、LinkedList等,如果这些容器是静态的,那么他们的生命周期与JVM一致,则容器中的对象在程序结束之前都不能释放。从而造成内存泄漏。
2.单例模式
和静态集合类类似,他们的生命周期与JVM一致,则容器中的对象在程序结束之前都不能释放。从而造成内存泄漏。
3.内部类持有外部类
如果一个外部类的实例对象的方法返回了一个内部类的实例对象。这个内部类被长期引用了,即使那个外部类对象不被使用,但是由于内部类持有 外部类的实例对象,这个外部类对象将不会被垃圾回收。
4.各种连接
如:数据库连接、网络连接、IO连接等。不使用需要关闭。
5.不合理的作用域
一般而言,一个变量的定义的作用范围大于其使用范围,很可能会造成内存泄漏。另一方面如果没有及时的把对象设置为NULL, 很有可能导致内存泄漏的发生。
6.改变hash值
当一个对象被存储进hashset集合中以后,就不能修改那些参与计算哈希值的字段了。否则对象修改后的哈希值与最初存进hashset 的哈希值不一样,这样会导致检索不到对象,也无法从hashset集合中删除当前对象,造成内存泄漏。
7.缓存泄漏
并非redis缓存,而是使用hashMap之类的当做缓存用于初始化等作用。
8.监听器和回调
在API中注册回调,却没有显示的取消,那么就会积聚。