首页 > 其他分享 >JVM个人详细笔记总结

JVM个人详细笔记总结

时间:2024-07-25 09:56:04浏览次数:11  
标签:总结 笔记 XX GC 垃圾 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的关系

标签:总结,笔记,XX,GC,垃圾,JVM,方法,加载
From: https://blog.csdn.net/wrxfxdd/article/details/140607658

相关文章

  • C++自学笔记15(数组)
    指针是C++中数组的工作方式,没有指针基础可以看笔记6。数组就是一堆变量的集合,有没有感觉与结构体很相似?让我们来考虑下在结构体中我们仅仅是定义了几个变量例如定义x,y坐标与speed速度。如果我们需要64个变量表示某个东西的64种状态,那么你会看到inta0=0;inta1=1;inta2......
  • C++自学笔记16(字符串与字符串字面量)
    当我们想在电脑上以文本方式表示东西时,一个单词、一个句子、一大段文章都叫做字符串。字符串就是为了我们去处理文字文本的方法。字符串实际上就是字符组成的数组或指针(数组就是指针的一种)。(有人会问数组不是储存数字么?怎么储存字符?因为ASCLL码表将所有字母、数字、符号翻译......
  • 【笔记】矩阵的行列式
    定义行列式(Determinant)是对\(n\)阶方阵\(A\)定义的,是一个标量。\(A\)的\(n\)阶行列式\(\operatorname{det}(A)\)或\(|A|\)定义如下:\[\operatorname{det}(A)=\sum_p(-1)^{\operatorname{sgn}(p)}\prod_{i}A[i][p_i]\]这里将排列的奇偶性定义为了\(\operatorname{sgn......
  • C++学习笔记(03)——通讯录管理系统设计
    记录一下利用C++来实现一个通讯录管理系统系统中需要实现的功能如下:添加联系人:向通讯录中添加新人,信息包括(姓名、性别、年龄、联系电话、家庭住址)最多记录1000人显示联系人:显示通讯录中所有联系人信息删除联系人:按照姓名进行删除指定联系人查找联系人:按照姓名查看指定联系人......
  • HASC 2024 游记 & 总结
    HASC2024游记&总结Day-2~-1请了刚毕业的学长来扫盲,强度很高,从线性代数到离线分治,涉及知识点很广,但都是过基础,感觉还不错,作业也都写的差不多,但是整体二分老师过了两遍还是没怎么懂qaq,想着集训再补吧。Day0集训报到!当天还下了大雨,走路走到学校的,几乎是刚到学校就开始下......
  • vue大小写总结
    1.组件组件的定义有两种命名方式:PascalCase  和   kebab-casePascalCase 定义的组件的引用:PascalCase  和   kebab-case  均可//PascalCase定义方式Vue.component('MyComponentName',{/*...*/})//引用方式一<my-component-name/>//引用方......
  • JS笔记第六期(DOM练习)-使用JS实现用户添加删除
    要实现的界面为:界面的CSS样式:*{ margin:0auto;}th,td{ width:200px; height:50px; text-align:center; font-size:20px;}.tBox{ border:#0000001pxsolid; width:450px; height:250px; margin:0auto; padding:10px; }JS+HTML:<!DOCTYP......
  • 弦图 学习笔记
    弦图学习笔记定义弦图中任意\(k\ge4\)阶环都有弦,等价于对于任意导出子图都不是\(k\ge4\)阶环。单纯点单纯点的邻域是团。完美消除序列(akapeo)点的排列,使得\(\foralli,v_i\)在\(\{v_i,v_{i+1},...,v_n\}\)的诱导子图中是单纯点。点割集\((u,v)\)的点割......
  • 树形 dp 学习笔记
    状态设计基本上每一种dp都有一种标准的dp定义方式,树形dp也是如此:定义\(f[u]\)表示以\(u\)为根节点的子树里最优的决策。从分析子树入手,转移便是找到某一子树中,根节点与各子树、边权间的递推关系。最优解常常是关于根节点的函数。它的子结构是一颗子树。实现方式......
  • 测开学习路线笔记
    Pytest源码包含了很多插件入口点(调用插件)如何搭建一个测试平台Django在线编辑Excel、yaml文件Pytest读取执行,生成测试报告、日志记录Django展示结果和测试报告如何开发一个Pytest插件HOOK:约定查看源码hookspec.py查看文档HOOK规则:被动调用(被pytest自......