JVM深入学习(一)

[复制链接]
发表于 2025-11-4 13:37:40 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
目次
一.JVM概述 
1.1 为什么要学jvm?
1.2 jvm的作用 
1.3 jvm内部构造
二.JVM类加载
2.1类加载过程
2.2类加载器
2.3类加载器的分类
2.4双亲委派机制
 三.运行时数据区
堆空间地区分别(堆)
为什么分区(代)?(堆)
对象创建存储过程(堆)
jvm调优
方法区的垃圾接纳(方法区)


一.JVM概述 

1.1 为什么要学jvm?

         1.口试的必要。 
         2.高级步调员必要相识 。
1.2 jvm的作用 

        jvm负责把编译后的字节码转徐徐为呆板码。
1.3 jvm内部构造

类加载部分负责把硬盘上的字节码加载到内存中(运行时数据区)。
运行时数据区负责存储运行时产生的各种数据,类信息,对象信息,方法信息...
实验引擎负责将字节码转为呆板码。
本地方法接口 调用本地方法。
Object类中的hashCode()--对象内存中的地点。
read0()方法调用利用体系,利用体系返回数据。
 垃圾接纳
 使用引用计数法或可达性分析法来判定对象是否存活。
二.JVM类加载

类加载体系:负责将硬盘上的字节码文件加载到jvm中,天生类的Class对象,存储在方法区。 
2.1类加载过程

        1.加载:以二进制文件流举行读取 ,在内存中为类天生Class对象。
        2.链接:
                验证:验证文件格式是否精确,字节码文件都以(CAFEBABE标识开头)
                准备:为类的静态属性分配内存,并举行初始化赋值(不包罗final修饰的)如:static int n=123;准备阶段先赋值默认0,初始化阶段时赋值123。
                留意:不包罗用 final 修饰的 static 常量,在编译时举行初始化。
                 分析:将类中的符号引用更换为直接引用(把字节码的符号引用更换成内存中的直接引用)

3.初始化:(类加载完成的标志)
        初始化阶段重要是为类中静态成员举行赋值。
        由于类加载实验完初始化,才分析类加载完成了。
类在哪些环境下会被加载
        1.调用类中的静态成员(变量(不是final修饰的常量),方法)
        2.new类的对象
        3.在类中实验main方法
        4.反射加载类(Class.forName()天生的class对象)
        5.子类被加载
类在以下两种环境下,是不会被加载的
   1. 类作为数组范例
Demo demo[] = new Demo[10]; //new 的数组对象   不是Demo对象,Demo只是作为范例存在
  2.只是访问类中的静态的常量
System.out.println(Demo.P);//优化   不加载整个类了,  只获取到用到的静态常量
  2.2类加载器

        类加载器就是实际负责读取类的功能.
        类加载器分类: 站在jvm的角度上, 分为
        1.引导类加载器(不是用java写的,是用c/c++),负责读取加载java中底层体系库
        2.java写的类加载器(用来读取我们写的应用步调)
 输出为null,分析为引导类加载器写的,能输出则为java写的。
2.3类加载器的分类

再细分类加载器:
        1.启动类加载器
   C/C++语言实现,负责加载java焦点类库(体系库,java.lang)
          2. 扩展类加载器 
   用java语言实现,继续ClassLoader类,加载jre包下面的扩展类的jre/lib/ext子目次
          3.应用步调类加载器
   用Java语言实现,继续ClassLoader类,用来加载我们自己的应用步调类
  2.4双亲委派机制

           当加载一个类时,总是先让他的父级类加载器去加载,确保把体系中类优先加载,直到父类加载器找不到类时, 再逐级向下,让子级类加载器加载,假如子级也找不到, 终极抛类找不到非常。这就是双亲委派机制。
  

为什么如许做?
防止我们自己写的类更换了体系中的类(如:String类)
   怎样突破双亲委派机制?
  自界说类加载器:MyClassLoader extends ClassLoader  
  重写findClass()
   三.运行时数据区

        存储运行时产生的各种数据
步调计数器        用来记录每一个线程实验的指令位置,速率最快,是线程私有(每个线程都会有一个步调计数器),此地区不会出现内存溢出(不敷用),也不会出现垃圾接纳。
假造机栈 栈是运行的,办理步调方法实验。
在假造机中,运行我们java自己写的方法
调用方法时,方法入栈,运行竣事出栈 (先辈后出 栈顶的方法,称为当前栈帧)
一个方法就是一个栈帧,,在栈帧中存储局部变量,运行结果....
假造机栈也是线程私有的,线程之间相互隔离
栈地区不存在垃圾接纳, 但是会存在内存溢出标题。
栈帧中存储内容:1.局部变量表 int a =10;    2.利用数栈 (盘算过程) int c = a+b;
3.方法返回地点
本地方法栈         是用来实验调用的本地方法的,是线程私有的,不会存在垃圾接纳,会出现内存溢出标题。
堆 堆的作用是用来存储java语言产生的对象的。
是运行时数据区中最大的一块内存空间, 空间巨细可以设置。
堆空间是全部线程共享的。
堆空间是垃圾接纳(没有用的垃圾对象,有周期性)的重点地区, 堆中没有被使用到的垃圾对象,会被垃圾接纳器接纳掉。有大概出现内存溢出。
方法区 方法区重要用来存储加载类的信息。
方法区的巨细也是可以设置的。
方法区也会举行垃圾接纳, 方法区也大概会出现内存溢出标题。
堆空间地区分别(堆)

堆分为:新生区(新生代/年轻代):伊甸园区、幸存者0区、幸存者1区
              老年区(老年代)

为什么分区(代)?(堆)

        可以将差异生命周期的对象存储在差异的地区,差异的地区接纳差异的垃圾接纳算法,使垃圾接纳计谋更加优化。

对象创建存储过程(堆)

   新创建的对象都存储在伊甸园区。(如上述的图)
  当垃圾接纳时,将还被使用的对象,转移至某一个幸存者区,将伊甸园区垃圾对象举行扫除。
  当下次垃圾接纳时,将伊甸园区存活的对象与当前正在使用的幸存者区存活的对象转移到另一个幸存者区(每次空闲一个幸存者区)。
  当一个对象履历过15次垃圾接纳后,仍然存活,那么就把该对象移动到老年代。
  对老年代比力少的举行垃圾接纳,在老年代空间不敷时,对老年代会举行垃圾接纳。
  当接纳后,内存仍然不敷时,会出现FULL GC(整堆网络 应只管克制)。
  当整堆网络后仍然不敷使用,那么就会出现内存溢堕落误 --- OOM(OutOfMemoryError)
  
jvm调优

        可以根据步调具体的使用场景, 对①运行时数据区的各种空间巨细举行调解 比方:堆,方法区
②对垃圾接纳器举行选择

方法区的垃圾接纳(方法区)

        方法区的垃圾接纳, 是对类信息举行接纳的。
        类信息假如不再被使用,类信息也可以被卸载。
   卸载条件:①该类所产生的对象都不存在了。
                    ②该类的Class对象,也不再被使用了。
                    ③ 加载该类的类加载器也被接纳了。
   感谢你的阅读与关注,如有标题接待探究!💓
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表