JVM概念及优化

本文详细介绍了JVM的概念、整体架构、内存结构,包括虚拟机栈、堆、方法区的详细划分,并重点讲解了垃圾回收机制,涉及引用类型及其在内存管理中的作用。通过对JVM的学习,有助于提升对Java应用的性能优化和问题排查能力。
摘要由CSDN通过智能技术生成

系列文章目录

JVM概念及优化



前言

我们知道一个Java 应用部署后,会时不时出现问题。除去网络、系统本身问题,很多时候 Java 应用出现问题,就是 Java 虚拟机的内存出现了问题。要么是内存溢出了,要么是 GC 频繁导致响应慢等等。
通过对JVM的学习,不但能深入理解java这门语言,还能为未来排查线上问题打下基础。


一、JVM

1.1、什么是JVM

JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。

在这里插入图片描述
从图中可以看到,有了 JVM 这个抽象层之后,Java 就可以实现跨平台了。JVM 只需要保证能够正确执行 .class 文件,就可以运行在诸如 Linux、Windows、MacOS 等平台上了。


1.2、JVM整体架构

java代码执行过程

在这里插入图片描述
由上图可看出,java代码先是编译为class文件,通过类加载系统,进入jvm内存空间等待执行,执行完后,通过垃圾收集器回收空间。
下面我们来看下jvm的架构图,及其内部的主要流程。


jvm架构图

在这里插入图片描述
由上图可看出,JVM分为五大模块: 类装载器子系统 、 运行时数据区 、 执行引擎 、 本地方法接口 和 垃圾收集模块 。


1.3、 JVM思维导图

请添加图片描述


二、类加载


三、JVM内存结构

根据 JVM 规范,JVM 内存共分为虚拟机栈、堆、方法区、程序计数器、本地方法栈五个部分。

在这里插入图片描述


3.1、PC程序计数器


3.2、虚拟机栈

Java虚拟机栈(Java Virtual Machine Stacks)也是线程私有的,即生命周期和线程相同。Java虚拟机栈和线程同时创建,用于存储栈帧。

栈帧(Stack Frame)是用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直到执行完成的过程就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。


3.3、本地方法栈


3.4、堆

Java堆(Java Heap) 是虚拟机所管理的内存中最大的一块。 Java堆是被所 有线程共享的一块内存区域, 在虚拟机启动时创建。 此内存区域的唯一目的就是存放对象实例,所以是垃圾收集器管理的主要区域。


3.4.1、分类

由于现在收集器基本都采用分代收集算法,所以Java堆还可以细分为:新生代和老年代;新生代又可以分为:Eden 空间、From Survivor空间、To Survivor空间。

jdk1.7级以前

在这里插入图片描述

jdk1.8级以后

在这里插入图片描述

年轻代和老年代区别:

  • 年轻代主要存放新创建的对象,内存大小相对会比较小,垃圾回收会比较频繁。年轻代分
    成1个Eden Space和2个Suvivor Space(from 和to)。
  • 年老代主要存放JVM认为生命周期比较长的对象(经过几次的Young Gen的垃圾回收后仍
    然存在),内存大小相对会比较大,垃圾回收也相对没有那么频繁。

在这里插入图片描述

年轻代和老年代配置:

  • 默认 -XX:NewRatio=2 , 标识新生代占1 , 老年代占2 ,新生代占整个堆的1/3
    修改占比 -XX:NewPatio=4 , 标识新生代占1 , 老年代占4 , 新生代占整个堆的1/5

Eden和Survivor配置:

  • 默认 -XX:SurvivorRatio=8 , Eden空间和另外两个Survivor空间占比分别为8:1:1
    可以通过操作选项 -XX:SurvivorRatio 调整这个空间比例。

3.4.2、对象分配过程

在这里插入图片描述

  • 1.new的对象先放在伊甸园区。该区域有大小限制;
  • 2.当伊甸园区域填满时,程序又需要创建对象,JVM的垃圾回收器将对伊甸园预期进行垃圾回收(Minor GC),销毁伊甸园区域中不再被其他对象引用的对象,加载新创建的对象;
  • 3.然后将伊甸园区中的剩余对象移动到幸存者0区;
    – 如果再次触发垃圾回收,将幸存的对象移至幸存者1区;
    – 如果再次经历垃圾回收,此时会重新返回幸存者0区,接着再去幸存者1区;
  • 4.如果累计次数到达默认的15次,就会进入老年代。可以通过设置参数,调整阈值 -XX:MaxTenuringThreshold=N;
  • 5.老年代内存不足时,会再次出发GC:Major GC 进行老年代的内存清理;
  • 6.如果老年代执行了Major GC后仍然没有办法进行对象的保存,就会报OOM异常.

3.4.3、堆与GC


主动FullGC

① FullGC时,会STW,导致大量请求超时,我们可以通过监控+告警,当内存不足时,主动触发.
方法:
循环创建 new byte[] 1m, 通过监控jvm内存空间,决定创建几个,比如1G内存就是1024个

② jmap指令


3.5、方法区

方法区(Method Area) 与Java堆一样, 是各个线程共享的内存区域, 它用于存储已被虚拟机加载 的元数据【类】信息、常量、 静态变量、 即时编译器编译后的代码缓存等数据。元空间、永久代是方法区具体的落地实现。

类信息:

① 这个类型的完整有效名称(全名 = 包名.类名)
② 这个类型直接父类的完整有效名(对于 interface或是java.lang. Object,都没有父类)
③ 这个类型的修饰符( public, abstract,final的某个子集)
④ 这个类型直接接口的一个有序列表


域信息,即为类的属性,成员变量

JVM必须在方法区中保存类所有的成员变量相关信息及声明顺序。
域的相关信息包括:域名称、域类型、域修饰符(pυblic、private、protected、static、final、volatile、transient的、某个子集)


方法信息:

  1. 方法名称方法的返回类型(或void)
  2. 方法参数的数量和类型(按顺序)
  3. 方法的修饰符public、private、protected、static、final、synchronized、native,、abstract的一个子集
  4. 方法的字节码bytecodes、操作数栈、局部变量表及大小( abstract和native方法除外)
  5. 异常表( abstract和 native方法除外)。每个异常处理的开始位置、结束位置、代码处理在程序计数器中的偏移地址、被捕获的异常类的常量池索引。

常量池

常量池,可以看做是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等类型。

常量池表Constant pool table:
在这里插入图片描述
在方法中对常量池表的符号引用

在这里插入图片描述


3.5.1、永久代

在这里插入图片描述


3.5.2、元空间


四、JVM内存模型JMM


五、垃圾回收GC

5.1、引用类型

Java中的对象引用分为四种,强引用类型、软引用类型、弱引用类型、虚引用类型。
Java中提供这四种引用类型主要有两个目的:
第一是可以让程序员通过代码的方式决定某些对象的生命周期;
第二是有利于JVM进行垃圾回收。使用软引用和弱引用可以有效的避免oom。软引用关联的对象,只有软引用关联时,才可回收,如果有强引用同时关联,不会回收对象占用的内存,弱引用也如此。

引用类型特点
强引用宁愿抛出OOM,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。
软引用用来描述一些有用但并不是必需的对象,内存空间不足时,就会回收这些对象的内存。
弱引用当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。
虚引用在任何时候都可能被垃圾回收器回收。虚引用必须和引用队列(ReferenceQueue)联合使用。

5.2、引用案例

软引用

	public void testSoftReference() {
	    Map<String,SoftReference<Bitmap>> imagesCache = new HashMap<String,SoftReference<Bitmap>>();
	    Bitmap bitmap = getBitmap();
	    SoftReference<Bitmap> image1 = new SoftReference<Bitmap>(bitmap);
	    imagesCache.put("image1",image1);
	    SoftReference<Bitmap> result_SoftReference = imagesCache.get("image1");
	    Bitmap result_Bitmap = result_SoftReference .get();
	 
	}
	
	import java.lang.ref.SoftReference;
	 
	public class Main {
	    public static void main(String[] args) {
	        SoftReference<String> sr = new SoftReference<String>(new String("hello"));
	        System.out.println(sr.get());
	    }
	}

弱引用


虚引用

	import java.lang.ref.PhantomReference;
	import java.lang.ref.ReferenceQueue;
	 
	 
	public class Main {
	    public static void main(String[] args) {
	        ReferenceQueue<String> queue = new ReferenceQueue<String>();
	        PhantomReference<String> pr = new PhantomReference<String>(new String("hello"), queue);
	        System.out.println(pr.get());
	    }
	}


总结

提示:这里对文章进行总结:

例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。


参考资料:
1、Java内存结构(JVM)与内存模型(JMM)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值