首页 > 其他分享 >必知必会:JVM

必知必会:JVM

时间:2023-06-18 20:46:22浏览次数:44  
标签:必知 对象 GC 内存 JVM 必会 线程 加载

JVM-Java虚拟机

Java程序运行时,编译器将Java文件编译成平台无关的Java字节码文件(.class)。对应平台JVM对字节码文件进行解释,翻译成对应平台匹配的机器指令并运行。

  • JVM内存区域(内存结构)

JVM内存区域粗略划分为堆和栈。
按虚拟机规范划分为五部分,包括程序计数器、虚拟机栈、本地方法栈、堆、方法区(永久代)。
在JDK1.8中变成了程序计数器、虚拟机栈、本地方法栈、堆、元空间。

(1)程序计数器:也叫PC寄存器,是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器,字节码解释器依次读取指令,实现流程控制。
(2)Java虚拟机栈:是线程私有的,为JVM执行Java方法服务,用来存储局部变量、操作数栈、动态连接等。
(3)本地方法栈:和Java虚拟机栈类似,但差别本地方法栈是为JVM使用到的本地native方法服务。
(4)Java堆:所有线程共享的一块内存区域,在虚拟机启动时创建,存放的是对象实例。
(5)方法区:所有线程共享的一块内存区域,存放已被虚拟机加载的类型信息、常量、静态变量、字符常量池、即时编译器编译后的代码(class)等。
(6)元空间:JDK1.8中,元空间代替了方法区。

  • Java堆的内存分区

Java堆又分为年轻代(新生代)和老年代。新生代存放存活时间短的对象,达到年龄后的对象会被移到老年代,老年代还存放大对象。
新生代又分为eden、survivors,survivors分两个区域:from、to,这三者的比例是8:1:1。

  • 堆、栈区别

(1)堆内存是不连续的;栈是连续的。
(2)堆是所有线程共享的;栈是线程私有的。
(3)堆存放的是对象实例和数组;栈存放的是局部变量、操作数栈等。

  • JVM类加载过程

JVM类加载过程分为五个阶段:加载->链接->初始化->使用->卸载;链接阶段又包括验证->准备->解析。
(1)加载:通过类加载器加载Class文件字节码,在内存中生成class对象
(2)链接:
         验证:确保加载的class的正确性、安全性。
         准备:为类变量分配存储空间并设置类变量初始值。
         解析:JVM将常量池内的符号引用转换为直接引用。
(3)初始化:执行类变量赋值和静态代码块。
(4)使用
(5)卸载:执行了System.exit()方法,程序正常结束、程序在执行过程中出现异常/错误而终止、操作系统出错导致JVM进程终止。

  • 对象创建的过程

就是先执行类加载,再为新生对象分配内存并对象内存初始化,最后设置对象头。
(1)new指令
(2)检查类是否被加载:检查这个符号引用代表的类是否能在常量池中定位到一个类的符号引用。
(3)类加载、解析、初始化检查:如果没有被加载,则先执行相应的类加载过程。
(4)对象内存分配:虚拟机为新生对象分配内存。
(5)对象内存初始化:内存分配完成后,虚拟机将分配到的内存空间都初始化为零值,不包括对象头。
(6)设置对象头,请求头包含了对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等。

  • 内存溢出和内存泄漏

内存泄漏会导致内存溢出。
(1)内存溢出:申请的内存超过了可用内存,内存不够用了。
(2)内存泄漏:申请的内存空间没有被正常释放,导致内存被占用的浪费。

  • 说几种内存泄漏的场景

(1)定义了静态集合类,因为静态集合类的生命周期和JVM一样,所以集合引用的对象不能被释放啊
(2)IO没有正常被close啊,导致持续占用内存,不能被GC回收。
(3)变量的作用域不合理啊,或者不再使用的对象没有及时设置为null。
(4)ThreadLocal使用不当啊,用完记得要调用remove()方法啊。
(5)hash值发生变化啊,想使用HashMap、HashSet时,对象修改后的hash值和存储到容器时的hash值不同,就无法找到存入的对象单独删除啦。

  • 对象有哪几种引用

(1)强引用
(2)软引用
(3)弱引用
(4)虚引用

  • 逃逸分析技术了解吗?

逃逸分析:某个方法之内创建的对象除了在方法体内被引用外,还在方法体外被其他变量引用,导致在该方法执行完后,其创建的对象无法被GC回收。
方法逃逸:当一个对象被new出来后,如果对象是作为参数传递到外部了,这种是方法逃逸。
线程逃逸:一个对象被外部线程访问到,如对象赋值给可以在其他线程中访问的实例变量,这种叫线程逃逸。

逃逸分析的好处:栈上分配、同步消除、标量替换。
如果确定一个对象不会逃逸到线程之外,这个对象可以在栈上分配,对象占用的内存就会随着栈帧出栈销毁。这种情况,对象就不是分配在堆中的,减少GC压力。

  • 双亲委派

Java类加载器主要有四类:启动类加载器、扩展类加载器、系统类加载器、用户自定义类加载器。
双亲委派的工作过程:
(1)如果一个类加载器收到类加载请求,它是先把这个请求委派给父类加载器去完成,一层层向上委派至顶层的启动类加载器;
(2)从启动类加载器开始,判断自己能否完成加载请求;如果不能则父加载器再一层层向下判断自己能否完成,能完成就加载;
(3)如果最后都无法完成,则抛出异常。

  • Young GC、Full GC什么时候触发?

(1)Young GC:新创建的对象优先在新生代Eden区进行分配,如果Eden区没有足够的空间时,就会触发Young GC来清理新生代。
(2)Full GC:老年代空间不足;方法区由永久代实现,而永久代空间不足;System.gc()、jmap -dump等命令触发Full GC。

老年代空间不足判断又分为
(1)Young GC之前检查发现本次Young GC后可能升入老年代的对象大小要超过老年代当前可用内存空间,就会触发Full GC。
(2)Young GC之后有一批对象需放入老年代,这时如果没有足够内存空间,则立马触发Full GC。
(3)老年代内存使用率达到一定比例,也会触发Full GC。
(4)新生代对象GC年龄达到阈值,需要晋升到老年代,老年代空间不足,就会触发Full GC。

  • 对象什么时候会进入老年代?

(1)长期存活的对象移区年龄到达阈值后会进入老年代:
对象头信息中存储着对象的迭代年龄,每次YoungGC后对象的移区年龄加1,当到了设置的最大年龄15后,对象就会被移到老年代。
(2)大对象直接进入老年代。
(3)动态对象年龄判定:如果Survivor空间中相同年龄的对象总和内存占用超过Survivor空间的一半,则大于等于该年龄的对象直接移到老年代。
(4)空间分配担保:Young GC之后发现新生代还有大量对象存活,可能要把Survivor无法容纳的对象直接移到老年代。

  • JVM调优

频繁Young GC(minor GC):通常是由于新生代空间较小,可以通过增加新生代空间-Xmn来降低Young GC的频率。
频繁Full GC:先分析原因,可能原因有:
(1)系统一次性加载了过多数据到内存,大对象进入了老年代。
(2)频繁创建了大量对象,但无法被回收,导致内存泄漏,会先引发Young GC,再引发Full GC。
(3)长生命周期的对象,到了一定的阈值后被移到老年代。
(3)BUG。
(4)JVM设置参数不合理。


公司一般有全方位监控JVM各项指标的监控系统,可以上去看看分析:
平均YGC周期
Heap使用峰值,可以参考YGC周期中的峰值
FGC前后的Heap谷值
一周内FGC次数
元空间使用的峰值

  • JVM参数

Xms:分配内存最小值,4G、8G按需设置
Xmx:分配内存最大值
MaxNewSize:新生代最大值
MaxMetaspaceSize:元空间,一般512M
NewRatio:新生代与老年代的比例
新生代和老年代的比例一般设置为1:2
新生代占堆空间的1/3,老年代占2/3。

标签:必知,对象,GC,内存,JVM,必会,线程,加载
From: https://www.cnblogs.com/scorpio-cat/p/17489710.html

相关文章

  • 必知必会:MySQL
    复制表结构和其数据:createtabletable_name_newasselect*fromtable_name_old表结构相同,复制表数据:insertintotable_name_newselect*fromtable_name_old表结构不同,复制表数据:insertintotable_name_new(column1,column2...)selectcolumn1,column2........
  • 必知必会:Java基础
    创建对象有几种方式(1)new创建对象;(2)反射创建对象;(3)采用clone机制;(4)序列化机制。创建反射对象的几种方式(1)类.class:通过 类名.class 创建反射获取对象; 类.class 是静态加载,是JVM编译时就要加载。Class<ClassDemo>oClass=ClassDemo.class;(2) object.getClass() :以 实......
  • 美团一面:OOM后,JVM一定会退出吗?为什么?
    文章且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录博客园版为您奉上珍贵的学习资源:免费赠送:《尼恩Java面试宝典》持续更新+史上最全+面试必备2000页+面试必备+大厂必备+涨薪必备免费赠送:《尼恩技术圣经+高并发系列PDF》,帮你实现技术自由,完成职业升级,薪酬猛......
  • 申威3231_SPECJVM2008的测试结果与信创服务器对比验证
    申威3231_SPECJVM2008的测试结果与信创服务器对比验证背景周六找同事将在公司里的机器进行了开机.然后验证了config.guess和config.sub的确是可以通过复制/usr下面的文件进行解决的但是perl的很多model无法使用.所以没办法,准备测试一把SPECJVM2008其实周五晚上看......
  • JVM(一)
    一、JVM介绍1、运行Java字节码的虚拟机。字节码和不同系统的JVM实现是Java语言“一次编译,随处可以运行”的关键所在。2、负责程序运行时的内存管理。提供了垃圾自动回收机制,无需程序员手动释放内存3、提供类加载机制,将字节码文件转为机器码4、提供异常处理机制  在......
  • 聊聊Flink必知必会(四)
    概述FlinkStreamingAPI借鉴了谷歌数据流模型(GoogleDataFlowModel),它的流API支持不同的时间概念。Flink明确支持以下3个不同的时间概念。Flink明确支持以下3个不同的时间概念。(1)事件时间:事件发生的时间,由产生(或存储)事件的设备记录。(2)接入时间:Flink在接入事件时记录的......
  • JAVA JVM 层面的锁
    JVM锁1、JAVA为了实现在多线程环境灰姑娘下的线程安全,提供了诸如synchronized,ReentrantLock等工具类来解决我们在多线程环境下的线程安全问题。synchronized锁1、上面是synchronized锁synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:修饰一个代......
  • 聊聊Flink的必知必会(三)
    概述在进行流处理时,很多时候想要对流的有界子集进行聚合分析。例如有如下的需求场景:(1)每分钟的页面浏览(PV)次数。(2)每用户每周的会话次数。(3)每分钟每传感器的最高温度。(4)当电商发布一个秒杀活动时,想要每隔10min了解流量数据。对于这些需求的处理,程序需要处理元素组,而......
  • 2、【java程序运行监控byteman】使用示例(运行中方法耗时监控、javaagent监控、jvm监控
    (文章目录)本文介绍了byteman的其他几种应用场景及示例,比如javaagent、监控jvm、bmjava命令、如何查看运行的规则、检查规则的正确性、检查规则是否在运行中等。本文分为2个部分,即运行中方法耗时监控和其他示例。一、统计方法耗时(程序运行中)该类是实时显示控制台输入的结果以......
  • HTTP请求:requests模块基础使用必知必会
    1背景http请求是常见的一种网页协议,我们看到的各种网页,其实都是发送了http请求得到了服务器的响应,从而将数据库中复杂的数据以简单、直观的方式呈现出来,方便大众阅读、使用。而如何发送http请求呢?今天来探讨一下使用requests模块,达到高效、简单的http请求操作。2什么是request......