JVM知识总结(简单且高效)

news2024/12/24 4:02:10

1. JVM内存与本地内存

  • JVM内存:受虚拟机内存大小的参数控制,当大小超过参数设置的大小时会报OOM。
  • 本地内存:本地内存不受虚拟机内存参数的限制,只受物理内存容量的限制;虽然不受参数的限制,如果所占内存超过物理内存,仍然会报OOM。

2. JVM内存结构

  • 虚拟机栈:服务于Java方法
  • 本地方法栈:服务于本地方法
  • 程序计数器:保存当前线程执行的字节码位置,当然每个线程工作时都有独立的计数器。
  • 堆:用于存放对象
  • 方法区:用于存放常量、静态变量、数据类型、类信息等元数据
    在这里插入图片描述

3. 线程独占与共享区域

  • 独占:虚拟机栈、本地方法栈、程序计数器
  • 共享:堆、方法区

4. 栈与堆的区别

  • 栈:是运行时单位,代表逻辑,且区域连续
  • 堆:是存储单位,代表数据,区域不连续

5. 方法区、永久代、元空间

  • 方法区:是规范,是概念。
  • 永久代:是实现,在JDK7及之前版本,是方法区的一种实现。
  • 元空间:是实现,在JDK8及之后版本,是方法区的一种实现。(替代了永久代)
    在这里插入图片描述
    在这里插入图片描述

6. 元空间为什么替代了永久代

  • 突破内存限制,减少OOM。 由于元空间使用的是本地内存,而不是 JVM 内存。
  • 提高 Full GC 的效率。 因为永久代中存放了很多 JVM 需要的类信息,这些数据大多数是不会被清理的,所以 Full GC 往往无法回收多少空间。但在元空间模型中,由于字符串常量池已移至堆中,因此可以更有效地进行垃圾回收,避免了因频繁的 Full GC 导致的性能影响。
  • 满足不同的类加载需求和动态类加载的情况。 元空间可以动态地调整大小,在一些大型的、模块化的应用中,可能需要加载大量的类,这就需要大量的元数据存储空间。
  • 避免永久代调优和大小设置的复杂性。 在 Java8 之前的版本中,通常需要手动设置永久代的大小,以避免内存溢出的错误。这增加了应用的配置和管理的复杂性。而元空间使用本地内存,根据实际需求动态调整,大大简化了内存管理的复杂性。

7. JVM内存可见性

  • 线程对于变量的操作只能在自己的工作内存中进行,而不能直接对主存操作。
    在这里插入图片描述

8. 类的生命周期

  • 加载:通过类的完全限定名,查找此类字节码文件,并创建Class对象。
  • 验证:确保Class文件符合当前虚拟机的要求。
  • 准备:为static修饰的类变量分配内存,不包含final修饰的变量,因为final已经在编译时分配。
  • 解析:将常量池的符号引用替换为直接引用。
  • 初始化:静态块执行、静态变量赋值。
  • 使用:new出对象程序中使用。
  • 卸载:执行垃圾回收。
    在这里插入图片描述

9. 符号引用和直接引用

  • 符号引用即用**(用字符串符号的形式)**来表示引用,其实被引用的类、方法或者变量还没有被加载到内存中。而直接引用则是有具体引用地址的指针,被引用的类、方法或者变量已经被加载到内存中。

10. 类的初始化

只有对类主动使用时才会初始化,触发条件包括

  • 创建类的实例时。
  • 访问类的静态方法或静态变量的时候。
  • 使用Class.forName反射类的时候。
  • 某个子类初始化的时候。

11. 双亲委派加载机制

  • AppClassLoader从缓存查找类,没有则委托给父加载器ExtClassLoader
  • ExtClassLoader从缓存查找类,没有则委托给父加载器BootStrapClassLoader
  • BootStrapClassLoader从缓存查找类,没有则sun.mic.boot.class路径查找
  • BootStrapClassLoadersun.mic.boot.class路径查找,没有则让子类ExtClassLoader加载
  • ExtClassLoaderjava.ext.dirs路径查找,没有则让子类AppClassLoader加载
  • AppClassLoaderjava.class.path路径查找,如果找到就加载类,否则就抛出异常。
    在这里插入图片描述

12. 双亲委派机制的优点

  • 避免类的重复加载
  • 避免Java的核心API被篡改

13. GC如何判断对象可以被回收

  • 引用计数法:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收
  • 可达性分析法:从GC Roots开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的,那么虚拟机就判断是可回收对象

14. 可达性分析算法

  • 可达性算法中的不可达对象并不是立即死亡的,对象拥有一次自我拯救的机会
  • 当对象编程(GC Roots)不可达时,GC会判断该对象是否执行过finalize方法,若执行了则直接回收。否则,若对象未执行过finalized方法,将其放入F-Queue队列。执行finalize方法完毕后,GC会再次判断该对象是否可达,若不可达,则进行回收,否则对象复活。

15. 四种JVM的垃圾回收算法

标记-清除算法:标记无用对象,然后进行清除回收。缺点:效率不高,无法清除垃圾碎片。
标记-整理算法:标记无用对象,让所有存活的对象都向一端移动,然后直接清除掉端边界以外的内存。
复制算法:按照容量划分二个大小相等的内存区域,当一块用完的时候将活着的对象复制到另一块上,然后再把已使用的内存空间一次清理掉。缺点:内存使用率不高,只有原来的一半。
分代算法:根据对象存活周期的不同将内存划分为几块,一般是新生代和老年代,新生代基本采用复制算法,老年代采用标记整理算法。

16. 分代算法

  1. new新对象放入堆中
  2. 如果在Eden区没有空间,那就发生Minor GC,保留存活的对象
  3. 当新生代仍然没有空间,那就将部分年龄大的新生代对象放入老年代
  4. 当老年代仍然没有空间,那就发生Major GC,保留存活的对象
  5. Major GC之后仍然没有空间,就会抛出OOM
    在这里插入图片描述

17. 为什么会出现OOM

  • 内存泄漏:申请使用完的内存没有释放,导致虚拟机不能再次使用该内存,此时这段内存就泄露了。因为申请者不用了,而又不能被虚拟机分配给别人用
  • 内存溢出:申请的内存超出了 JVM 能提供的内存大小,此时称之为溢出内存泄漏持续存在,最后一定会溢出,两者是因果关系

18. 常见的OOM报错

方法区溢出

  • 报错信息:java.lang.OutOfMemoryError: PermGen space
  • 常见问题:一般出现于大量Class对象,或者方法区过小

栈区溢出

  • 报错信息:java.lang.StackOverflowError
  • 常见问题:一般是由于程序中存在 死循环或者深度递归调用 造成的,或者栈区过小

堆区溢出

  • 报错信息:java.lang.OutOfMemoryError: Java heap space
  • 常见问题:内存泄漏、内存溢出

19. OOM如何解决

  • 主要使用dump文件jprofiler两个工具,具体自行学习

20. JVM的元空间中会发生垃圾回收吗

  • 垃圾回收不会发生在元空间,如果元空间满了或者是超过了临界值,会触发完全垃圾回收(FullGC)。
  • 如果正确设置元空间大小,那么就可以避免Full GC

21. 查看相关线程命令

  • jps(JVM Process Status Tool):显示指定系统内所有的HotSpot虚拟机进程。
  • jstat(JVM statistics Monitoring):显示出类装载、内存、垃圾收集、JIT编译等运行数据。
  • jmap(JVM Memory Map):命令用于生成heap dump文件
  • jhat(JVM Heap Analysis Tool):命令是与jmap搭配使用,用来分析jmap生成的dump,jhat内
    置了一个微型的HTTP/HTML服务器,生成dump的分析结果后,可以在浏览器中查看
  • jstack:用于生成java虚拟机当前时刻的线程快照。
  • jinfo(JVM Configuration info):这个命令作用是实时查看和调整虚拟机运行参数。

22. Minor GC与Full GC分别在什么时候发生?

  • 新生代内存不够用时候发生MGC也叫YGC,JVM内存不够的时候发生FGC。

23. 对象一定分配在堆中吗?有没有了解逃逸分析技术?

  • 不一定的,JVM通过「逃逸分析」,那些逃不出方法的对象会在栈上分配。

24. 什么是逃逸分析

  • 方法逃逸:在一个方法体内,定义一个局部变量,而它可能被外部方法引用,比如作为调用参数传递给方法,或作为对象直接返回。或者,可以理解成对象跳出了方法。
  • 线程逃逸:这个对象被其他线程访问到,比如赋值给了实例变量,并被其他线程访问到了。对象逃出了当前线程。
  • 逃逸分析:没有发生逃逸的对象,会进一步优化,将其放在栈中
// sb就逃逸了
public static StringBuffer craeteStringBuffer(String s1, String s2) {
    StringBuffer sb = new StringBuffer();
    sb.append(s1);
    sb.append(s2);
    return sb;
}

// sb没有逃逸了
public static String createStringBuffer(String s1, String s2) {
    StringBuffer sb = new StringBuffer();
    sb.append(s1);
    sb.append(s2);
    return sb.toString();
}

25. 逃逸分析带来的好处

  • 同步省略:如果对象只能一个线程被访问到,那么对于这个对象的操作可以不考虑同步。
  • 将堆分配转化为栈分配:对象可能是栈分配的候选,而不是堆分配。
  • 分离对象:有的对象可以,那么对象的部分(或全部)可以不存储在内存,而是存储在CPU寄存器中。

26. 逃逸分析的开启关闭

  • 从jdk 1.7开始已经默认开始逃逸分析,如需关闭,需要指定-XX:-DoEscapeAnalysis
  • -XX:+DoEscapeAnalysis : 表示开启逃逸分析
  • -XX:-DoEscapeAnalysis : 表示关闭逃逸分析

27. 同步省略
动态编译同步块的时候,JIT编译器可以借助逃逸分析来证实同步块的对象只能够被一个线程访问,就会取消对这部分代码的同步,这个过程也叫锁消除

如以下代码:

public void f() {
    Object hollis = new Object();
    synchronized(hollis) {
        System.out.println(hollis);
    }
}

hollis对象的生命周期只在f()方法中,并不会被其他线程所访问到,所以在JIT编译阶段优化成:

public void f() {
    Object hollis = new Object();
    System.out.println(hollis);
}

28. 元空间为什么能替代永久代

  • 区别:永久代存在于JVM限制内存,元空间存在于本地内存。所以元空间会更大。
  • 好处:能够避免方法区OOM异常,虽然我们可以通过设置永久代的大小来解决OOM,但是不是总能知道应该设置为多大合适, 如果使用默认值很容易遇到OOM错误。当使用元空间时,可以加载多少类的元数据就由系统的实际可用空间来控制啦,即元空间具有伸缩性。

29. Stop The World

  • 进行垃圾回收的过程中,会涉及对象的移动。为了保证对象引用更新的正确性,必须暂停所有的用户线程,像这样的停顿,虚拟机设计者形象描述为「Stop The World」,也简称STW。

30. 指针碰撞

  • 分配方式:一般情况下,JVM的对象都放在堆内存中(发生逃逸分析除外)。当类加载检查通过后,Java虚拟机开始为新生对象分配内存。如果Java堆中内存是绝对规整的,所有被使用过的的内存都被放到一边,空闲的内存放到另外一边,中间放着一个指针作为分界点的指示器,所分配内存仅仅是把那个指针向空闲空间方向挪动一段与对象大小相等的实例。
  • 指针碰撞:如果现在两个线程同时创建对象呢?
    在这里插入图片描述

31. 空闲列表

  • 如果Java堆内存中的内存并不是规整的,已被使用的内存和空闲的内存相互交错在一起,不可以进行指针碰撞啦,虚拟机必须维护一个列表,记录哪些内存是可用的,在分配的时候从列表找到一块大的空间分配给对象实例,并更新列表上的记录,这种分配方式就是空闲列表。

32. 什么是TLAB

  • 每个线程都有自己的一小块内存,这就是TLAB(Thread Local Allocation Buffer,本地线程分配缓存) 。虚拟机通过 -XX:UseTLAB 设定它的。

33. JVM有哪些垃圾回收器

  • Serial:新生代、单线程、复制算法(适用于小堆、单核)
  • ParScavenge:新生代、多线程、复制算法、高吞吐
  • Serial Old:老年代、单线程、标记-整理(适用于大堆、多核)
  • ParOld:老年代、多线程、标记-整理、低交互
  • CMS:老年代、多线程、标记-整理、低停顿低吞吐
  • G1:全堆、多线程、标记-整理

附录

「堆栈内存相关」

-Xms 设置初始堆的大小
-Xmx 设置最大堆的大小
-Xmn 设置年轻代大小,相当于同时配置-XX:NewSize和-XX:MaxNewSize为一样的值
-Xss 每个线程的堆栈大小
-XX:NewSize 设置年轻代大小(for 1.3/1.4)
-XX:MaxNewSize 年轻代最大值(for 1.3/1.4)
-XX:NewRatio 年轻代与年老代的比值(除去持久代)
-XX:SurvivorRatio Eden区与Survivor区的的比值
-XX:PretenureSizeThreshold 当创建的对象超过指定大小时,直接把对象分配在老年代。
-XX:MaxTenuringThreshold设定对象在Survivor复制的最大年龄阈值,超过阈值转移到
老年代

「垃圾收集器相关」

-XX:+UseParallelGC:选择垃圾收集器为并行收集器。
-XX:ParallelGCThreads=20:配置并行收集器的线程数
-XX:+UseConcMarkSweepGC:设置年老代为并发收集。
-XX:CMSFullGCsBeforeCompaction=5 由于并发收集器不对内存空间进行压缩、整理,
所以运行一段时间以后会产生“碎片”,使得运行效率降低。此值设置运行5次GC以后对内
存空间进行压缩、整理。
-XX:+UseCMSCompactAtFullCollection:打开对年老代的压缩。可能会影响性能,但是
可以消除碎片

「辅助信息相关」

-XX:+PrintGCDetails 打印GC详细信息
-XX:+HeapDumpOnOutOfMemoryError让JVM在发生内存溢出的时候自动生成内存快照,
排查问题用
-XX:+DisableExplicitGC禁止系统System.gc(),防止手动误触发FGC造成问题.
-XX:+PrintTLAB 查看TLAB空间的使用情况

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1361290.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言学习NO.13-字符函数(三)-strncpy,strncat,strncmp长度受限制的字符串函数

长度受限制的字符串函数介绍 一、strncpy函数的使用 &#xff08;一&#xff09;strncpy使用 #include <stdio.h> #include <string.h>int main() {char arr1[20] "asdfgdfv";char arr2[7] "zxcvbn";strncpy(arr1, arr2, 4);printf("…

Origin无法使用主题管理器相关功能或报错:Err, Save Theme dialog error!

问题描述 在使用origin绘图时&#xff0c;往往需要进行大批量绘制同样类型的图。如果每个图都不断地去修改相关设置&#xff0c;无疑是浪费了许多宝贵的时间。为了提高绘图效率&#xff0c;了解到了主题管理器&#xff0c;可在“工具–主题管理器”找到。 然而&#xff0c;当我…

计算机毕业设计-----SSM宠物商城带后台管理系统

项目介绍 该项目为前后台项目&#xff0c;分为普通用户与管理员两种角色&#xff0c;前台普通用户登录&#xff0c;后台管理员登录&#xff1b; 用户角色包含以下功能&#xff1a; 加入购物车,发表留言,提交订单,查看订单信息,会员注册,登录页面等功能。 管理员角色包含以下…

静态网页设计——极乐迪斯科(HTML+CSS+JavaScript)

前言 声明&#xff1a;该文章只是做技术分享&#xff0c;若侵权请联系我删除。&#xff01;&#xff01; 感谢大佬的视频&#xff1a; https://www.bilibili.com/video/BV11k4y1X7mH/?vd_source5f425e0074a7f92921f53ab87712357b 使用技术&#xff1a;HTMLCSSJS&#xff08;…

C++补充内容--EasyX-UI界面

esay x 其他 地图打印(利用二维数组) 双缓冲 当我们绘制一张图 然后另一张图盖住前一张图的某个部分的时候 由于while的存在 会导致 两张图不停的闪烁 所以加入双缓冲可以解决这个问题 开启双缓冲 之后等待Flush或者End 才会进行图片的绘制 不然不会进行图片的绘制,这样就可…

Python学习之路——文件部分【文件的读取】

目录 先解释一下引文的答案 一、open()打开函数 二、mode常用的三种基础访问模式 三、读-操作相关方法 &#xff08;一&#xff09;read方法 &#xff08;二&#xff09;readlines方法 &#xff08;三&#xff09;with open 语法 &#xff08;四&#xff09;操作汇总 …

腾讯云2核2G3M服务器够用吗?腾讯云2核2G3M云服务器性能评测

阿里云轻量应用服务器2核2G3M带宽优惠价格62元一年&#xff0c;100%CPU性能&#xff0c;3M带宽下载速度384KB/秒&#xff0c;40GB SSD系统盘&#xff0c;月流量200GB&#xff0c;折合每天6.6GB流量&#xff0c;超出月流量包的流量按照0.8元每GB的价格支付流量费&#xff0c;地域…

【c++】vector模拟

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大二&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;能手撕vector模拟 > 毒鸡汤&#xff1a;在等待…

PCL提示无法读取强度信息(Failed to find match for field ‘intensity‘.)简单解决方法

问题&#xff1a; 使用CC或者其他软件将las或者其他格式点云转成PCD格式后&#xff0c;然后使用PCL的库进行读取&#xff0c;有时会碰到Failed to find match for field intensity.提示&#xff0c;解决方法如下&#xff1b; 处理方法&#xff1a; 一个比较简单的方法如下&…

对比开源大语言模型的自然语言生成SQL能力

背景 NL-to-SQL&#xff08;自然语言到结构化查询语言&#xff09;任务是自然语言处理&#xff08;NLP&#xff09;领域的一个难题。 它涉及将自然语言问题转换为 SQL 查询&#xff0c;然后可以针对关系数据库执行该查询来回答问题。 该任务是 NLP 中的一个专门子领域&#xf…

C++补充内容--语法篇

这里写目录标题 语法其他语法函数的存储类函数参数默认值格式默认参数位置重载函数的默认参数 指针名与正常指针的自增自减以及解引用与的优先级问题指针的赋值、加减数字、加减指针二维数组中的一些指针辨析输出调用字符指针时 会将该指针以及之后的元素全部输出二维数组未完全…

【力扣题解】P530-二叉搜索树的最小绝对差-Java题解

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【力扣题解】 文章目录 【力扣题解】P530-二叉搜索树的最小绝对差-Java题解&#x1f30f;题目描述&#x1f4a1;题解&…

【性能测试入门】详解客户端性能测试和服务器端性能测试!

一&#xff1a;客户端性能测试和服务器端性能测试 客户端性能测试和服务器端性能测试是两个不同但相关的概念: 客户端性能测试: - 测试应用程序客户端(如Web浏览器、移动应用等)的性能,例如加载时间,响应时间等。 - 测试在不同系统配置(CPU、内存、网络等)下客户端的运行性…

在Gitee上维护Erpnext源

在Gitee上维护Erpnext源 官方的frappe和erpnext地址: GitHub - frappe/frappe: Low code web framework for real world applications, in Python and Javascript GitHub - frappe/erpnext: Free and Open Source Enterprise Resource Planning (ERP) 1, 仓库地址输入frappe的官…

cissp 第10章 : 物理安全要求

10.1 站点与设施设计的安全原则 物理控制是安全防护的第一条防线&#xff0c;而人员是最后一道防线。 10.1.1 安全设施计划 安全设施计划通过关键路径分析完成。 关键路径分析用于找出关键应用、流程、运营以及所有必要支撑元索间的关系。 技术融合指的是各种技术、解决方案…

适用于生物行业的生信云平台

随着基因检测技术的不断发展&#xff0c;生物信息云平台在基因检测行业的应用越来越广泛。生物信息云平台是一种基于云计算的技术&#xff0c;可以将基因检测数据存储在云端&#xff0c;并通过数据分析、挖掘等技术手段&#xff0c;对基因数据进行处理、分析和解读。 这种技术的…

16、Kubernetes核心技术 - 节点选择器、亲和和反亲和

目录 一、概述 二、节点名称 - nodeName 二、节点选择器 - nodeSelector 三、节点亲和性和反亲和性 3.1、亲和性和反亲和性 3.2、节点硬亲和性 3.3、节点软亲和性 3.4、节点反亲和性 3.5、注意点 四、Pod亲和性和反亲和性 4.1、亲和性和反亲和性 4.2、Pod亲和性/反…

实战干货:用 Python 批量下载百度图片!

为了做一个图像分类的小项目&#xff0c;需要制作自己的数据集。要想制作数据集&#xff0c;就得从网上下载大量的图片&#xff0c;再统一处理。 这时&#xff0c;一张张的保存下载&#xff0c;就显得很繁琐。那么&#xff0c;有没有一种方法可以把搜索到的图片直接下载到本地电…

python实现圆圈烟花_附完整源码【第21篇—python过新年】

文章目录 前言效果图&#xff08;动态&#xff09;完整代码代码讲解总结寄语 前言 烟花是一种庆祝、欢庆或庆典活动中常见的美丽表现&#xff0c;它们以多彩的光芒和炫丽的形状为人们带来欢乐和惊喜。在这个项目中&#xff0c;我们将使用Python编程语言创建一个简单而有趣的程…

使用printJS使网页打印成PDF、网页html结合printJS导出为pdf

先放几个参考链接 感谢&#xff01; Vue使用PrintJS实现页面打印功能_vue print.js 设置打印pdf的大小-CSDN博客 前台导出pdf经验汇总 &#xff08;html2canvas.js和浏览器自带的打印功能-print.js&#xff09;以及后台一些导出pdf的方法_iqc后台管理系统怎么做到导出pdf-CSD…