JVM相关总结

系列文章目录

文章目录


一、案例

使用阿里的arthas去确认升级完的字节码文件是不是最新的

思路:

在出问题的服务器上部署一个arthas,并启动

连接arthas的控制台,使用jad命令加上想要查看的类名,反编译出源码

确认源码是否是最新的

二、前情提要

1、字节码文件的核心组成有哪些?

基本信息:魔数,字节码文件对应的java版本号,访问标识,父类,接口

常量池:保存了字符串常量,类和接口名,字段名

字段:当前类或者接口声明的字段信息

方法:当前类或者接口的方法信息字节码指令

属性:类的属性,比如源码的文件名,内部类的列表等

2、类的生命周期

2.1 加载

类加载器根据类的全限定名通过不同的渠道 以二进制流的方式获取字节码信息

(本地文件-磁盘上的字节码文件,程序运行时使用动态代理生成的类)

类加载器在加载完类以后,java虚拟机会将字节码中的信息保存到内存的方法去中,生成一个InstanceKlass对象(字节码文件:基本信息,常量池,字段,方法xx),保存类的所有信息,里边还包含实现特定功能比如多态的信息,同时,Java虚拟机还会在堆中生成一份与方法区中数据类似的java.lang.Class对象,

2.2 连接:

验证:验证字节码信息

准备:准备阶段为静态变量分配内存并设置初始值,final修饰的基本数据类型的静态变量,准备阶段直接会将代码中的值进行赋值

解析:将常量池中的符号引用替换为直接引用。符号引用就是在字节码文件中使用编号来访问常量池中的内容,直接引用就是使用内存地址直接访问

2.3 初始化

初始化阶段会执行静态代码块中的代码,并为静态变量赋值

初始化阶段会执行字节码文件中clinit部分的字节码指令

下面几种方式都会导致类的初始化

访问一个类的静态变量或者静态方法,注意变量是final修饰的并且右边是常量不会触发初始化

调用class.forName(xxxxx)

new 一个该类的对象时

执行main方法的当前类

3、类加载器

jdk8和之前的版本:
虚拟机底层实现

启动类加载器:加载java中最核心的类,启动类加载器是由Hotspot虚拟机提供的,使用C++编写的类加载器,默认加载java安装目录下/jre/lib下的类文件,比如rt.jar

java :允许扩展java中比较通用的类, 扩展类加载器和应用程序类加载器都是jdk提供的,使用java编写的类加载器,他们的源码都位于sun.misc.Launcher中,是一个静态内部类。继承自URLClassLoader。具备通过目录或者指定jar包将字节码文件加载到内存中

扩展类加载器:默认加载java安装目录jre/lib/ext下的类文件

应用程序类加载器:加载classpath下的类文件,以及第三方依赖的类文件

4、为什么需要双亲委派机制?

双亲委派指的是:自底向上查找是否加载过, 再由顶向下进行加载(向下委派起到了一个加载优先级的作用),向上查找如果已经加载过,就直接返回class对象,加载过程结束,这样就能避免一个类重复加载

保证类加载的安全性:通过双亲委派机制避免恶意代码替换JDK中的核心类库,比如java.lang.String, 确保核心类库的完整性和安全性

避免重复加载:避免同一个类被加载多次

5、为什么需要打破双亲委派机制?

三种方式:

自定义类加载器: 通过重写loadClass方法,就可以将双亲委派机制的代码去除

线程上下文类加载器:利用上下文类加载器加载类,比如JDBC和JNDI等

osgi框架的类加载器

三、Java中垃圾回收

1、Young GC=年轻代垃圾回收

仅针对新生代(eden区和s0,s1区), 当新生代内存,尤其是eden区被填满时触发,只回收新生代里的对象,老年代不受影响,回收频率较高,回收时间较短,因为新生代对象大多数都是周明周期短,容易被回收

1、Eden区空间不足---触发YGC

新生代被划分为三个区域:Eden区, s0区, s1区, 大部分新创建的对象会先分配到eden区

当eden区的对象填满,无法再为新的对象分配空间时,young gc会被触发,回收新生代中不再使用的对象

2、Eden区+S区都满了----触发YGC

如果eden区和s区的空间都不足以存放新分配的对象时,YGC也会被触发,清理空间并将幸存的对象转移到S区域老年代

3、部分垃圾回收器full gc之前---触发YGC

Parallel Scavenge垃圾回收器在full gc 之前先执行下YGC

2、old GC=老年代垃圾回收

只针对老年代,当老年代空间不足触发,通常是从新生代晋升到老年代对象或多,或者老年代存活对象数量达到一定一定阈值。执行方式是只回收老年代的对象,新生代不受影响,执行时间比young GC长,因为老年代中的对象存活时间长,数量多

3、Full GC=整堆垃圾回收

顾名思义,对整个堆进行回收,当老年代空间不足且取法通过老年代垃圾回收释放足够空间,或其他情况导致系统内存压力较大时触发,回收时间长,会触发整个JVM的停顿,对性能有影响

1、老年代--触发FGC

当老年代空间不足,且无法通过老年代垃圾回收释放足够空间,

2、永久代或者元空间不足

java8以前,如果永久代空间不足,会触发FGC, java8以后,永久代被移除,元空间取代了永久代,如果元空间内存不足,也可能触发FGC

3、调用system.gc, jmap-dump等命令

显示调用system.gc方法。可能会触发FGC

4、新生代晋升到老年代失败

年轻代的大对象或者长期存活的对象被晋升到老年代,如果老年代空间不足,也会触发FGC

四、OOM

oom表示JVM无法为应用程序分配足够的内存,导致程序崩溃

堆内存溢出:

java堆用于存放对象实例,如果创建了过多对象,或者内存泄漏导致对象无法被回收,会导致堆内存耗尽,如果有大量创建对象或者集合类的场景,持续增加数据但是未释放就会产生堆内存溢出

栈内存溢出:

每个线程都会有独立的栈空间,栈用于存储方法调用的信息,局部变量,方法参数等,如果方法调用层次特别深或者有无限递归,栈空间耗尽

方法区或者元空间溢出

java8以后,永久代被替换成元空间,用本地内存实现,在频繁加载和卸载类的情况下,会导致溢出

直接内存溢出

java nio使用直接内存来加快IO操作,该内存不受JVM堆内存的限制,如果分配过多的直接内存,超过了设置的最大值,也会导致内存溢出

线程数过多导致内存溢出

每个线程都需要栈空间和一定的操作系统资源,如果创建过多线程而超出操作系统的资源限制,可能无法再创建新的线程,导致OOM, 应该合理设置线程池的大小,避免无限创建新的线程

GC执行时间太长导致的溢出

五、python中垃圾回收

Python 也有垃圾回收机制(Garbage Collection, GC),但它的实现方式和 Java 的不同。虽然 Java 中有 YGC(Young Generation GC)、Old GC(Old Generation GC) 和 Full GC 等概念,Python 并没有完全相同的分类,但它的垃圾回收机制同样负责自动管理内存,避免内存泄漏

复制代码
Python 使用的是 引用计数(Reference Counting) 作为主要的垃圾回收机制,
同时结合了 分代收集(Generational Garbage Collection) 和 循环检测(Cycle Detection)
 来处理复杂的内存管理问题

1、引用计数(Reference Counting)

每个对象都有一个引用计数器。

当一个对象被引用时,引用计数加一;当引用被移除时,引用计数减一。

当引用计数为 0 时,该对象会被立即回收。

2、分代收集(Generational GC)

Python 将对象分为三个"代":

第 0 代(Generation 0):新创建的对象,频繁回收

第 1 代(Generation 1):在第 0 代中存活下来的对象

第 2 代(Generation 2):在第 1 代中存活下来的对象

与 Java 不同的是,Python 的分代机制不是基于内存区域划分,而是基于对象的生命周期长短。

3、循环检测(Cycle Detection)

对于无法通过引用计数回收的循环引用对象(如两个互相引用的列表),Python 使用 标记-清除(Mark-Sweep) 算法来识别并回收这些对象。

4、触发时机

自动触发:

内存使用达到一定阈值时(由 gc 模块控制)

手动触发

执行 gc.collect() 手动触发

相关推荐
coderxiaohan3 小时前
【C++】类和对象1
java·开发语言·c++
ChillJavaGuy4 小时前
常见限流算法详解与对比
java·算法·限流算法
sali-tec4 小时前
C# 基于halcon的视觉工作流-章34-环状测量
开发语言·图像处理·算法·计算机视觉·c#
寻星探路4 小时前
数据库造神计划第六天---增删改查(CRUD)(2)
java·大数据·数据库
毕设源码-朱学姐4 小时前
【开题答辩全过程】以 4S店汽车维修保养管理系统为例,包含答辩的问题和答案
java·spring boot·汽车
盖世英雄酱581365 小时前
Read timed out问题 排查
java·数据库·后端
狼爷5 小时前
破解 JetBrains 的学生,后来都成了它的 “推销员”:一场用习惯换市场的长期战
java·jetbrains
你怎么知道我是队长5 小时前
C语言---循环结构
c语言·开发语言·算法
艾醒5 小时前
大模型面试题剖析:RAG中的文本分割策略
人工智能·算法