JVM浅析

J V M 类 加 载 流 程 和 内 存 结 构
图解:

一、类的加载classLoader

 1、类的主动加载方式(4种,经常被问到):
    1>构造函数:eg:Student student = new Student();
    2>反射、Clone;
    3>初始化子类的时候父类会被初始化;
    4>调用一个静态方法。
2、类加载的过程:
   1>加载 Loader
        通过类的全路径名,获取类的二进制数据;
        解析流,将类的信息存放于方法区;
        创建class类的实例。
   2>验证
   		验证加载字节码是否合法。
   3>准备
   		虚拟机为这个类分配内存空间
   4>解析
   		将符号引用转化为直接引用。关于二者的概念区别可参考:https://www.cnblogs.com/shinubi/articles/6116993.html
   5>初始化
   		此时,类已经被顺利加载到系统中,类开始执行java字节码。

二、JMM(Java Memory Manager)

1、  程序计数器
		有一个比较小的内存空间;
		正常的非native方法:字节码的行号指示器,native方法为空;
		内存私有;
		唯一的一个没有规定任何OOM情况的区域。
2、本地方法栈
		为native方法服务。
3、虚拟机栈
		私有的;
		描述方法执行的内存模型(栈帧);
		方法的执行到结束对应栈帧的入栈和出栈。

在这里插入图片描述

4、方法区/永久代/元空间
		共有的。
		方法区:存放类的信息、常量池、方法数据、代码等,是个逻辑上的概念。
		永久代(JDK7及之前):内存中不会被GC的一块永久区域;加载了类信息和元数据信息(关于元数据可参考https://blog.csdn.net/CSDN4006600/article/details/100268792);如果空间被加载的类信息占满,就会发生OOM异常。
		元空间(JDK8及之后):永久代因为可能产生OOM被元空间取代,元空间直接使用了本地内存;虚拟机整合,合二为一HopSpot、JRockit(原来没有永久代)。
5、堆
		共有的;
		创建的对象或者数组保存的地方;
		GC发生的地方;
		新生代(eden、s0、s1)和老年代。

三、标记一个垃圾对象

可触及性:确定一个对象是不是可以被回收;
从根节点开始,访问某个对象,如果能访问到,说明这个对象是可用的,反之,是不可用的;
可触及-->可复活(标记为垃圾对象时会调用一次finalize方法,给对象唯一一次复活的机会)-->不可触及。
public class DieAliveObject {
	private static DieAliveObject dieAliveObject;
	public static void main(String[] args) {
		dieAliveObject = new DieAliveObject();
		for (int i = 0; i <= 1; i++) {
			System.out.println(String.format("----------GC nums=%d----------", i));
			dieAliveObject = null; // 被标记
			System.gc(); // 通知JVM可以进行回收
			try {
			    Thread.sleep(100); // 等待GC执行
			 } catch (InterruptedException e) {
				e.printStackTrace();
			}
		    if (dieAliveObject == null) {
				System.out.println("dieAliveObject is null");
			} else {
				System.out.println("dieAliveObject is not null");
			}
	 }
}
 /**
 ** 仅调用一次,给对象一次复活机会
 *
 ** @throws Throwable
 */
 @Override
 protected void finalize() throws Throwable {
	System.out.println("finalize is calledѺ");
	super.finalize();
	dieAliveObject = this; // ֵ对象复生,添加引用
}

}

四、引用级别

1、强引用:程序中的引用;
2、软引用:堆空间不足时才会被回收。
3、弱引用:发生GC时,只要发现弱引用就会被回收;
4、虚引用:与没有引用一样。

五、槽位复用

可参考https://blog.csdn.net/weixin_38106322/article/details/108063173

六、对象的分配

在这里插入图片描述

1、栈上分配
	1>逃逸分析(变量或对象没在方法区内)
	2>标量替换
		标量:不可进一步分解的量(int、long等);
		聚合量:可以被进一步分解的量。
	3>替换
		通过逃逸分析,确定该对象会不会被外界访问;用标量去替代聚合量。
2、TLAB分配
	TLAB:Thread Local Allocation buffer,线程本地分配的缓冲区;
    作用:自己使用自己的缓冲区,避免多线程之间的获取控件的冲突;
    因为仅为缓冲区,所以内存空间比较小,没办法分配大的对象。
3、堆分配:绝大多数对象的分配方式。

七、常用的垃圾回收算法

	偏向策略:【分代算法;分区算法】

常用垃圾回收算法

八、垃圾回收器

1、串行回收器--serial古老
	特点:只使用单线程进行GC,独占式GC;单cpu情况下效率高。
2、并行回收器P a r N e w & P a r a l l e l G C & P a r a l l e l O l d G C
	将串行回收器多线程化;
	与串行回收器有相同的回收策略、算法、参数。

CMS垃圾回收过程

并行回收器JVM参数
3、G1:garbage first garbage collector
优先回收垃圾比例最高的区域,将堆划分为多个区域,每次收集部分区域来减少GC产生的停滞时间,作用域全域。
G1回收划分区域
初始标记根节点,初始标记和跟区域扫描针对新生代,直接标记可以去老年代的对象,并发标记即标记存活对象。重新标记:停止所有应用程序,最后的标记阶段,避免前面在应用程序跑的时候遗漏的。独占清理:计算存活比例,获取垃圾最多的区域。
并发标记周期
混合收集:对占比较高的 进行清理。
在这里插入图片描述

九、JVM常用参数

JVM常用参数1
JVM常用参数2

十、JVM监控优化

性能监控工具
LINUX top命令
LINUX top命令1
LINUX top命令2
LINUX vmstat命令
LINUX  vmstat命令
LINUX Iostat命令
LINUX  Iostat命令
J D K 工 具 j p s
J D K 工 具   j p s
J D K 工 具 j s t a t
J D K 工 具    j s t a t
J D K 工 具 j i n f o
J D K 工 具    j i n f o
J D K 工 具 j m a p
J D K 工 具    j m a p
J D K 工 具 j h a t
J D K 工 具    j h a t
J D K 工 具 j s t a c k
J D K 工 具     j s t a c k
J D K 工 具 j c m d
J D K 工 具    j c m d

如有描述不准确的,欢迎指正,互相学习!

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值