• JVM知识点


    JVM整体体系

    在这里插入图片描述

    类加载过程

    加载->检验->准备->解析->初始化

    1. 加载:使用类加载器查找并加载类的字节码文件
      • BootstrapClassLoader:是 ExtClassLoader 的父类加载器,所谓父类加载器并不是直接的继承关系,而是在ClassLoader parent属性中指定。默认加载 %JAVA_HOME%/lib 目录下的 jar包和class文件
      • ExtClassLoader:是 AppClassLoader 的父类加载器,默认加载%JAVA_HOME%/lib/ext 下的jar包和java类
      • AppClassLoader:是自定义加载器的父类加载器,负责加载classpath下的文件
    2. 检验:确保被加载的类的正确性
      • 格式验证:如验证是否符合class文件规范
      • 语义验证:如final修饰的类是否有子类等
    3. 准备:为类的静态成员变量分配空间并且赋予默认值
    4. 解析:将常量池的符号引用变成直接引用
    5. 初始化:给类的静态变量赋初始值。如果有静态代码块就执行static代码块中定义的所有操作。如果父类没有初始化则优先对父类进行初始化。

    JVM必须确保一个类在初始化的过程中,只能允许一个线程对其执行初始化操作。

    类加载器

    类加载器(ClassLoader)用来加载 Java 类到 Java 虚拟机中。基本上所有的类加载器都是 java.lang.ClassLoader 类的一个实例。
    在这里插入图片描述

    每一个类加载器,都拥有一个独立的类名称空间。对于任意一个类,都是由加载它的类加载器和这个类本身来确定唯一性的,即如果相同的class文件被不同的加载器所加载就属于不同的类

    比较两个类是否相等,只有在这两个类是由同一个类加载器加载的前提下才有意义。

    双亲委派机制

    每个类加载器都有自己的缓存空间和加载路径,加载一个类的时候会从AppClassLoader 开始向上查找每个加载器的缓存,判断缓存中是否加载了该类(findLoadedClass),如果加载了则直接返回,若到了BootstrapClassLoader(parent == null)都没有找到,则会查找 BootstrapClassLoader 的加载路径是否包含该类(findClass),如果包含则直接返回,否则继续往下查找,直到找到为止。

    这就是双亲委派机制, 向上找缓存,向下找加载路径。

    好处:

    1. 避免了类的重复加载
    2. 保证了安全性

    jvm内存结构

    虚拟机栈

    虚拟机栈:每个线程运行方法时需要的内存空间。

    每次调用方法都将该方法压入栈中,每个方法运行时在栈中需要的内存称为栈帧。正在执行的方法对应的栈帧称为活动栈帧

    每个新线程都会开辟属于自己的虚拟机栈,也就是说虚拟机栈是线程私有的,里面放的都是局部变量,记录着返回值、返回地址等。

    tips-Xss 可设置虚拟机栈的大小,如-Xss10m 将虚拟机栈设为10m

    • 问题:方法内的局部变量是否线程安全?
      1. 如果这个局部变量是形参或者函数返回值,那么可能是非线程安全的。
      2. 如果这个局部变量引用了对象,并且该对象逃离了方法的作用域,则可能是非线程安全的。

    栈帧

    一个栈帧需要分配多少内存,不会受到程序运行期变量数据的影响,而仅仅取决于具体的虚拟机实现。

    局部变量表(Local Variable Table)

    • 用于存储方法参数和方法内的局部变量的变量值。
    • 局部变量表的容量以 变量槽 为最小单位,每个变量槽都可以存储 32 位长度的内存空间。基本类型数据、引用和返回地址占用一个变量槽,long 和 double 需要两个。

    操作数栈(Operand Stack)

    • 临时存放方法执行过程中用到的变量值,也会经常进行入栈出栈操作。例如算术运算、方法参数的传递、返回结果的存放

    动态链接(Dynamic Linking)

    • 每个栈帧都包含一个指向 运行时常量池 中该栈帧所属方法的引用。

    **返回地址(Return Address) **

    • 返回到上一个方法的调用的地方。方法开始执行后只有两种方式可以退出:方法返回指令,异常退出。

    本地方法栈

    本地方法:非java代码编写的方法。因为java代码不能直接与操作系统底层API打交道,需要c或c++。在java类中用native修饰的方法就是本地方法

    本地方法栈:给本地方法提供内存空间。

    堆中存放着非静态全局变量和对象的实际位置(即new的对象都放在这里)。

    堆中还划分了eden区、servivor区(包含From和To区)还有old区,年轻代都在eden区和servivor区,达到一定年龄的对象会进入old区。

    特点:

    • 线程共享
    • 存在垃圾回收机制
  • 相关阅读:
    【服务器数据恢复】服务器光纤共享存储互斥失败的数据恢复案例
    前端Canvas入门——怎么用Canvas画一些简单的图案
    多数元素(Java版)
    我的Quick Latex For Obsidian-Setting(持续更新)
    Gitlab 设置页面语言为简体中文
    [NAS] Synology (群晖) DSM7.0 使用自定义供应商DDNS
    apisix~集成服务发现注册中心
    Partition架构
    国产720亿参数开源免费模型来了!对标Llama2 70B,一手实测在此
    【控制】基于Matlab实现含最速跟踪微分器的自抗扰控制技术
  • 原文地址:https://blog.csdn.net/qq_47431361/article/details/125625656