JVM调优

常用命令

1.列出java进程

jps   

2.列出jvm信息

jinfo pid  

在这里插入图片描述
-XX:InitialHeapSize:最小堆大小
-XX:MaxHeapSize:最大堆大小

3.查看java统计信息

jstat -gc pid 

4.动态查看java统计信息

jstat -gc pid 500 :每隔500ms统计信息

5.查看消耗资源进程

top 

6.查看jvm内存图

jmap -histo pid | head -20

在这里插入图片描述
7.生成hprof图

jmap -dump:format=b,file=/opt/filename.hprof 109018     109018为pid

JVM内存结构

程序计数器
作用:记录下一条jvm指令的执行地址(物理上通过寄存器实现的)
特点:线程私有的,不会内存溢出


栈:对象的引用,局部变量,实例方法。
每个线程都有栈,一个栈有多个栈帧组成,栈帧就是每个方法运行时需要的内存(参数,局部变量,返回地址)
问题:
1.垃圾回收是否涉及栈内存?
不会,方法会自动出栈
2.栈内存会越大越好吗?
栈内存越大,线程数越小
3.方法内的局部变量是否线程安全?
局部变量在方法作用范围内,是线程安全的,反之不安全。

栈内存溢出:1.栈帧过多,for循环调用 2.栈帧过大

线程诊断
cup占用居高不下(linux环境):

1. top 查看进程的cpu占用情况
2. ps H -eo pid,tid,%cpu 查看cpu的pid,线程tid,cpu占比
3. ps H -eo pid,tid,%cpu | grep 32456 查看进程号32456  的相关pid,tid,cpu情况
4. jstack 进程id
5. 第三步中的tid由10进制换算成16进制,找到nid对应的值如nid=0x7f99(尽量给线程池取名字,查看进程的线程数:
ls /proc/{pid}/task | wc -l)

本地方法栈
不是由java代码编写的代码(C,C++)


存放new出来的对象,线程共享的,需要考虑线程安全
有垃圾回收机制

堆内存溢出情况(OutOfMemoryError)

堆内存诊断
jconsole工具
jvisualvm工具

案例:垃圾回收后,依然内存很高

jvm运行时指定堆内存溢出时下载dump文件
nohup java -jar -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/ demo1-0.0.1-SNAPSHOT.jar &

方法区
存放着静态变量 + 常量 + 类信息(构造方法/接口定义) + 运行时常量池存在方法区中

StringTable性能调优(jdk1.8 StringTable存放在在堆内存中)
调整-XX:StringTableSize=桶个数
考虑将字符串对象是否入池(intern())
直接内存(NIO)

垃圾回收

1.如何判断对象可以回收
引用计数法:一个对象被其他变量引用就加一,不再引用就减一。
弊端:循环引用问题。
可达性分析算法:没有被root对象直接或间接引用的对象可以被回收。
哪些对象可以作为GC Root?
系统类(String,bject),本地方法引用的Java类,同步锁(syn),活动线程使用的对象(Thread)

1.强引用
例子:
Person p1 = new Person();

2.软引用
将p1引用交给别的对象,垃圾回收时,软引用不会清空,只有堆对象内存快满时才会被回收。

3.弱引用
将p1引用交给别的对象,垃圾回收时,弱引用会被清空。

4.虚引用
p1 = null时,会被清空。

5.终结器引用

垃圾回收算法

引用计数法
概述:
给每个对象一个计数器,对象被引用一次加一,不被引用时减一。计数为0时被定位为垃圾
缺点:不高效
标记清除算法
概述:
Collector 从引用根节点开始遍历,标记所有被引用的对象。一般是在对象的 Header 中记录为可达对象。标记的是引用的对象,不是垃圾!!
速度快,但是产生内存碎片问题
标记整理算法
概述:
可达性分析算法对对象进行标记,整理部分则是将存活的对象向内存空间一端进行移动,然后直接清理掉边界以外的内存区域。
优点:解决了“标记-清除算法”的空间碎片化问题
缺点:由于内存碎片的移动,效率比较低
复制算法
概述:将内存一分为二,将存活的对象复制到空的内存区域。
缺点:内存空间利用率不高

占用的内存空间较多

类加载器

概念:
java文件通过编译器变成了.class文件,接下来类加载器又将这些.class文件加载到JVM中。

类加载的过程:
类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。

什么是双亲委派:
会先交由AppClassLoader去加载,这时目前的ClassLoader不会去加载,而是一直向上,让父类去加载。

Bootstrap classLoader:主要负责加载核心的类库(java.lang.*等),构造ExtClassLoader和APPClassLoader。
ExtClassLoader:主要负责加载jre/lib/ext目录下的一些扩展的jar。
AppClassLoader:主要负责加载应用程序的主函数类

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值