文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

JVM(Java虚拟机)详解(JVM 内存模型、堆、GC、直接内存、性能调优)

2023-08-30 19:48

关注

JVM 内存模型 结构图

jdk1.8 结构图(极简)

在这里插入图片描述


jdk1.8 结构图(简单)

JVM(Java虚拟机):

在这里插入图片描述


jdk1.7 结构图(详细)

在这里插入图片描述


JVM 内存模型 组成元素

Java 内存模型主要包含线程私有程序计数器java虚拟机栈本地方法栈线程共享堆空间元数据区直接内存


Java 程序内存 = JVM 内存 + 本地内存


堆外内存


JVM 堆及各种 GC 详解

参考:Java 中的新生代、老年代、永久代和各种 GC

结构图(新生代、老年代、永久代)

JVM 中的堆,一般分为三大部分:新生代、老年代、永久代( Java8 中已经被移除)

在这里插入图片描述


新生代、MinorGC(Young GC)

新生代


MinorGC


老年代、MajorGC(Old GC)

老年代


永久代、元数据区(元空间)、常量池

永久代(PermGen)

元数据区(元空间、Metaspace)


元空间替换永久代的原因分析:


类常量池、运行时常量池、字符串常量池

拓展


Full GC 、Major GC(Old GC)

Minor GC、Major GC、Full GC 的区别

Full GC 触发机制:


堆空间分成不同区的原因


堆不是对象存储的唯一选择(逃逸分析)

如果经过逃逸分析后发现,一个对象并没有逃逸出方法的话,那么就可能被优化成栈上分配。这样无需在堆上分配内存。也无须进行垃圾回收了。

逃逸分析概述: 一种可以有效减少 Java 程序中同步负载和内存堆分配压力的跨函数全局数据流分析算法。

逃逸分析的基本行为就是分析对象动态作用域:


GC(垃圾回收)

System.gc()


如何检测应用程序正在进行 System.gc()?


如何禁止GC显式调用或调整调用GC的频率?

如果就是想避免程序员显式调用GC,避免不成熟的程序员在不合适时间调用GC,避免人为造成的GC崩溃,可以通过如下方法:


STW(Stop The World)事件

stop-the-world,简称 STW,指的是 GC 事件发生过程中,会产生应用程序的停顿。停顿产生时整个应用程序线程都会被暂停,没有任何响应,有点像卡死的感觉,这个停顿称为 STW。

可达性分析算法中枚举根节点(GC Roots)会导致所有 Java 执行线程停顿。

被 STW 中断的应用程序线程会在完成 GC 之后恢复,频繁中断会让用户感觉像是网速不快造成电影卡带一样,所以需要减少 STW 的发生。

STW 事件和采用哪款 GC 无关,所有的 GC 都有这个事件。哪怕是 G1 也不能完全避免 Stop-the-world 情况发生,只能说垃圾回收器越来越优秀,回收效率越来越高,尽可能地缩短了暂停时间。

STW 是 JVM 在后台自动发起和自动完成的。在用户不可见的情况下,把用户正常的工作线程全部停掉。

开发中除非特殊情况,不要用 system.gc() 进行手动 GC,会导致 stop-the-world 的发生。


GC 常用算法


直接内存(Direct Memory)详解

参考:JVM 直接内存

文件的读写过程

演示案例(运行并比较时间后可以发现,尤其是读写大文件时使用 ByteBuffer 的读写性能非常高):

// 演示ByteBuffer作用public class Demo {static final String FORM = "D:\\asd\\asd.mp4"; // 选比较大的文件,比如200多兆static final String TO = "D:\\asd.mp4";static final int _1Mb = 1024 * 1024;public static void main(String[] args) {        // io 用时:3187.41008(大概用了3秒),多跑几遍,多比较,跑一次不算。io();        // directBuffer 用时:951.114625(不到1秒)derectBuffer();}private static void deirectBuffer() {long start = System.nanoTime();try (FileChannel from = new FileInputStream(FROM).getChannel();FileChannel to = new FileOutputStream(TO).getChannel();) {ByteBuffer bb = ByteBuffer.allocateDirect(_1Mb); // 读写的缓冲区(分配一块儿直接内存)while (true) {int len = from.read(bb);if (len == -1) {break;}bb.flip();to.write(bb);bb.clear();}}catch (IOException e) {e.printStackTrace();}long end = System.nanoTime();print("directBuffer用时:" + (end - start) / 1000_000.0);}// 用传统的io方式做文件的读写private static void io() {long start = System.nanoTime();try ( // 网友1:写到try()括号里就不用手动close了FileInputStream from = new FileInputStream(FROM);FileOutPutStream to = new FileOutputStream(TO);) {byte[] buf = new byte[_1Mb];// byte数组缓冲区(与上面的读写缓冲区设置大小一致,比较时公平)while (true) {int len = from.read(buf);// 用输入流读if (len == -1) {break;}to.write(buf, 0, len);// 用输出流写}}catch(IOException e) {e.printStackTrace();}long end = System.nanoTime();print("io用时:" + (end - start) / 1000_000.0);}}

直接内存的分配和回收

直接内存的分配和释放是 Java 通过 UnSafe 对象来管理的,并且回收需要主动调用 freeMemory() 方法,不直接受 JVM 内存回收管理。

ByteBuffer 底层分配和释放直接内存的大概情况

演示案例(演示直接内存溢出)

// 演示直接内存溢出public class Demo {static int _100Mb = 1024 * 1024 * 100;public static void main(String[] args) {List<ByteBuffer> list = new ArrayList<>();int i = 0; try {while (true) {ByteBuffer byteBuffer = ByteBuffer.allocateDirect(_100Mb);// 每次分配100兆内存list.add(byteBuffer);// 把这玩意放到List中,一直循环i++;}}finally {print(i);}}}

使用 System.gc() 间接进行直接内存的回收可能存在的问题


JVM 的性能调优

调优参数

配置方式


内存参数:


垃圾回收器参数

JVM给了三种选择:串行收集器、并行收集器、并发收集器。串行收集器只适用于小数据量的情况。


元空间参数:

当进行过 Metaspace GC 之后,会计算当前 Metaspace 的空闲空间比,如果空闲比小于这个参数,那么虚拟机将增加 MetaspaceSize 的大小(为了避免过早引发一次垃圾回收)。

默认值为40,也就是40%。

设置该参数可以控制 Metaspace 的增长的速度,太小的值会导致 Metaspace 增长的缓慢,Metaspace的使用逐渐趋于饱和,可能会影响之后类的加载。而太大的值会导致 Metaspace 增长的过快,浪费内存。


辅助参数

JVM提供了大量命令行参数,打印信息,供调试使用。商业项目上线的时候,不允许使用。一定使用 loggc。主要有以下一些:


调优建议

来源地址:https://blog.csdn.net/footless_bird/article/details/128921448

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-人工智能
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯