JVM个人详细笔记总结

jvm概念和运行过程

jvm是java的虚拟机位于操作系统层之上,应用程序层之下,所以才具有跨平台能力,JAVA文件需要通过JVM转译成字节码或通过javac命令编译为.class文件后才能运行JAVA程序,运行时必须要有JRE(运行环境),JDK是开发包,其中包含有JRE。

jvm组成

JVM 结构主要分为三个部分:类加载器,运行时数据区,执行引擎

类加载器(Class Loader):

类加载器负责将类文件加载到 JVM 中运行时数据区中的方法区/元空间。JVM 内置了三个主要的类加载器:

启动类加载器:负责加载 Java 核心类库,是 JVM 自带的类加载器,其中启动类加载器BootstrapClassLoader是native方法,C语言实现的

扩展类加载器:负责加载 JVM 扩展目录中的 JAR 文件。

应用程序类加载器:负责加载应用程序类路径(Classpath)上的类。

执行引擎(Execution Engine):

执行引擎负责执行字节码。常见的执行引擎有两种:解释器,即时编译器

解释器:逐行解释执行字节码,执行效率较低。

即时编译器:将字节码一次性编译成本地机器码指令,生成可执行文件,执行效率更高。

运行时数据区(Runtime Data Area):方法区,堆,栈,程序计数器
方法区/元空间

方法区/元空间/非堆区/堆外内存都是一个意思,主要存储类信息、类的静态变量,常量,运行时常量池,他是jdk8开始用来代替之前堆里的永久代,元空间使用的是本地内存,可以动态调整内存大小,避免永久代内存溢出问题,

方法区相关总结

1.类的信息以及类的静态变量和常量直接存储在方法区的,没有存储在常量池

2.类信息包括类的名称、访问修饰符、字段、方法、父类、接口等信息。

3.方法区信息是各个线程共享的。

4.方法区的大小决定了系统可以保存多少个类,如果系统定义了太多的类也会导致方法区溢出。关闭 JVM 就会释放这个区域的内存。

拓展

1.可以通过String类的intern()方法将字符串放入字符串常量池中。

2.字面量

int a=1; // 这个1便是字面量
String b="iloveu"; // iloveu便是字面量

3.符号引用

定义:引用其他类的地址如:com.javabc.Quest就是符号引用

作用:由于在编译过程中并不知道每个类的地址,因为可能这个类还未加载,所以如果在一个类中引用了另一个类,被引用的类的全限定类名(com.javabc.Quest)会作为符号引用,在类加载完后用这个符号引用去获取它的内存地址

4.运行时常量池:是所有常量池的运行时表示形式,包括类常量池(主要存放字面量和符号引用)、方法常量池,字符串常量池等,

5.常量池作用:为了提高运行效率,减少内存的重复占用,并且为了方便JVM对程序的解释和执行。

堆:

一个JVM只有一个堆,用于存储对象实例。堆内存的大小可以通过参数调整,垃圾收集器扫描的主要区域就是中存储对象的实例,如果堆内存满了,并且垃圾收集器释放不了任何对象,就会OOM

jdk8后堆结构

jdk1.7及之前堆结构分为新生代(Eden,s0,s1),老年代,永久代,

jdk8后永久代被数据区中的元空间代替,就只有新生代(Eden,s0,s1)和老年代

新生代Eden:被创建的对象实例一开始都在Eden,Eden与S0,S1的默认比例是 8 :1 : 1

新生代S0(from区):如果某个对象活过了第一次垃圾收集,那么就会加入S0

新生代S1(To区):GC收集垃圾的复制算法时,会复制S0存活的对象实例到S1,然后在清除整个S0

老年代:

对象每活过一次GC,年龄都会+1,一旦年龄达到了老年代的门槛(15次GC没被回收),就会加入老年代

当老年代满了之后,JVM就会出发FullGC,扫描整个堆进行垃圾回收,一般情况下只会进行轻量级GC,minor GC

拓展

永久代:

JDK8之前叫永久代,JDK8之后叫元空间,他们的区别就是元空间在直接内存中,不在JVM运行时内存中

JDK8后常量池转移到了元空间中

JDK1.7开始常量池已经在堆中了

主要存储JDK自身携带的class对象,interface元数据,运行时环境

当出现OOM时导出DUMP文件,Dump文件可以在项目路径下看到,后缀为.hprof使用工具分析

栈(先进后出):

栈是先进后出的,并且是线程私有的,每个线程执行时都会创建一个栈,每个方法执行时都会在栈里创建一个栈帧,用来存储局部变量、方法调用和方法返回地址。

虚拟机栈:

虚拟机栈执行的是 java 方法,

本地方法栈:

本地方法栈执行的是 native 方法,是用其他语言(如 C、C++)编写的,通过 Java Native Interface(JNI)调用

栈相关问题:

1.如果当前线程栈中有方法递归调用或方法调用链过长,超过了栈的深度限制可能会抛出栈溢出 (StackOverFlowError)异常,

2.如果 Java 虚拟机栈容量可以动态扩展,当栈扩展时无法申请到足够的内存也会报OOM异常

2.虚拟机栈和本地方法栈都是栈,具有相同的特性,只是执行的方法类型不同

3.栈的大小可以在启动时固定,也可以动态地分配和扩展。

4.栈不存在垃圾回收问题,只要线程一结束该栈就释放,生命周期和线程一致。

程序计数器:

每个线程都有自己的程序计数器,用于记录当前线程正在执行的 Java 字节码指令的地址。他可以确保线程切换后能够继续执行原来的代码,也用于记录方法之间的跳转信息,例如方法调用和返回地址。

类加载过程

JVM 的类加载过程包括加载,验证、准备、解析和初始化五个阶段。

加载:

加载阶段是由类加载器将类的字节码文件(.class文件)从磁盘加载到内存中,

验证:

验证阶段主要保证安全问题。

主要验证文件格式是否符合Class格式规范,字节码中的(类、字段、方法)是否符合JVM规范,以及方法调用参数和返回类型是否正确,还有符号引用验证是否规范

准备:

准备阶段jvm会给类的静态变量分配内存并设置初始值(默认零值),静态变量会分配在方法区中。

解析:

符号引用是一种符号来描述所引用的目标,解析阶段将类、接口、字段和方法的符号引用解析为直接引用,是可以直接定位到目标的指针、句柄或偏移量,也就是和实际的内存地址关联起来。

初始化:

初始化阶段是对类的静态变量进行初始化,以及执行静态代码块。表示类准备好被使用了。

双亲委派

双亲委派是Java类加载机制中的一种机制,用于保证类的唯一性和安全性。确保在不同类加载器中加载的类不会互相冲突。避免恶意同名类的加载

过程:

当一个类加载器(称为子类加载器)需要加载一个类时,它首先不会自己尝试加载,而是将请求委托给其父加载器(称为父类加载器)去完成。

父类加载器也会按照相同的方式,首先委托给它的父加载器,以此类推,一直到顶层的启动类加载器(Bootstrap ClassLoader)。

如果父加载器无法找到所需的类,子类加载器才会尝试加载。

垃圾回收算法:

JVM 自动管理垃圾回收,主要回收不再被引用的对象,释放内存空间。

复制算法 (新生代):

主要用于新生代的垃圾回收,因为生命周期较短,适合用复制算法来回收,将堆分为两个区域,每次只使用其中一个区域。垃圾回收时,将存活的对象复制到另一个区域,然后清空原区域。

新生代GC触发机制:当新生代满(Survivor 满不会引发 GC)时就会触发新生代GC(通过复制算法回收垃圾)

标记-整理算法 (一般是老年代):

主要用于老年代的垃圾回收。

在标记阶段,标记存活对象。然后将存活对象向一端移动,最后清除边界以外的内存,保持存活对象的连续性。

标记-清除算法 (一般是老年代):

这个算法是基本的垃圾回收算法,但不常用于新生代和老年代的垃圾回收。

在标记阶段,它会标记所有存活的对象。在清除阶段,它会清除所有未标记的对象。

老年代GC触发机制:一般在进行老年代GC 前都先进行了一次 新生代GC,使得有新生代的对象晋身入老年代,导致空间不够用时才触发。或者当空间不够分配给新创建的对象时也会触发老年代GC 进行垃圾回收

老年代的对象生命周期较长, MajorGC比较费时,所以也不会频繁执行,也可以通过手动调用System.gc()来触发。

JVM调优
堆内存调优:

-Xms: 设置堆的初始大小。

-Xmx: 设置堆的最大大小。

-XX:NewRatio: 设置新生代(Young Generation)与老年代(Old Generation)的大小比例。

-XX:MaxNewSize :设置新生代的最大大小和。

-XX:MaxTenuringThreshold:设置升级到老年代的门槛次数

垃圾回收调优:

-XX:+UseSerialGC, -XX:+UseParallelGC, -XX:+UseConcMarkSweepGC, -XX:+UseG1GC: 选择不同的垃圾回收器。

-XX:SurvivorRatio: 设置新生代 Eden 区和 Survivor 区的比例。

-XX:MaxGCPauseMillis: 设置垃圾回收最大暂停时间目标。

栈和线程调优:

-Xss: 设置线程栈的大小。

-XX:ThreadStackSize: 设置线程栈大小的通用参数。

JIT 编译器调优:

-XX:+TieredCompilation: 启用分层编译。

-XX:CompileThreshold: 设置方法被 JIT 编译的调用次数阈值。

使用工具分析应用程序性能:

使用 Java 性能分析工具(如 VisualVM、JProfiler、YourKit)来分析应用程序的性能瓶颈和资源利用情况。

GC 日志与分析:

使用 -XX:+PrintGC、-XX:+PrintGCDetails 等参数打印 GC 日志,以便分析垃圾回收情况。

JVM,JRE,JDK的关系

📢 加入我们的Java技术交流群!

我们创建了一个专门针对Java技术爱好者的交流平台,目的只是为了纯粹探讨技术难题、分享心得与资源。无论您是初学者还是资深开发者,在这里都能找到志同道合的朋友!

🌟 群内特色:

专业讨论:专注于Java及相关技术栈的深度探讨;

互助成长:遇到问题时,总有人愿意伸出援手;

无广告环境:为了保持群内的纯净氛围,我们坚决抵制任何形式的广告行为。

👉 如何加入:

扫描下方二维码直接加入;

加入时请备注:[您的主要语言]+[从业年限](例如:Java 3年);

如果二维码已过期,请私信联系我获取最新入口。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wrx繁星点点

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值