zoukankan      html  css  js  c++  java
  • JVM学习(1):类加载机制

    Class文件结构解析:

    网上看到几篇文章对Java的Class文件解析写的比较全面:

    https://www.jianshu.com/p/247e2475fc3a

    http://tech.dianwoda.com/2018/03/28/jvm-classjie-xi-wen-jian-ge-shi/

    https://blog.csdn.net/hywo125/article/details/90770393

    类加载机制:

    第一步:加载

    1.获取二进制字节流

    2.静态存储结构转化为方法区的运行时数据结构

    运行时数据区有:【方法区,堆】,【虚拟机栈,本地方法栈,程序计数器】

    3.在Java堆中生成一个类对象,作为方法区的访问入口

    第二步:验证

    1.验证Class文件标识:魔术Magic Number:cafebabe

    2.验证Class文件版本号

    3.验证常量池(常量类型,常量类型数据结构是否正确,UTF-8是否符合标准)

    4.Class文件的每个部分(字段表、方法表等)是否正确

    5.元数据验证(父类验证、继承验证、final字段验证等)

    6.字节码验证,最复杂的步骤(指令验证)

    7.符号引用验证(验证通过符号引用是否能够找到字段、方法、类)

    在验证期间会报的错:

    IncompatibleClassChangeError--->Class文件错误

    Unsupported major.minor version xx.x--->版本有问题(通常指JDK版本问题)

    IllgalAccessError;NoSuchFieldError;NoSuchMethodError等等

    第三步:准备

    为类变量分配内存并且设置类变量的初始化阶段,只对static类变量进行内存分配

    例:(1)static int n=1;(2)static final int n=2;

    在初始化时的区别:

    (1)情况初始化后,初始化的值是0,而不是2,因为这时候还没执行任何Java方法,静态块最后是又CLINT调用的

    (2)情况对应到常量池(ConstantValue),在准备阶段n已经被赋值为2

    类变量和实例变量的区别:

    类变量:一般称为静态变量

    实例变量:当对象被实例化的时候,实例变量随着对象创建而创建,随着对象的销毁而销毁

    第四步:解析

    对符号引用进行解析,把符号引用变为直接引用

    直接引用:指向目标的指针或者说是一个偏移量

    主要涉及:类、接口、字段、方法等

    以下的类型:

    CONSTANT_Class_info

    CONSTANT_Field_info

    CONSTANT_Methodref_info

    CONSTANT_InterfaceMethodred_info

    CONSTANT_MethodType_info

    CONSTANT_MethodHandler_info

    CONSTANT_InvokeDynamic_info

    1.字段的解析:

    在本类中找有没有匹配的字段--->如果类有接口,往上层接口找匹配的字段--->搜索父类

    例如:

    class A extends B implements C,D{
    private String str;
    }

    搜索顺序:先在A类(本类)找,然后从C,D类(父接口)中找,接下来去B类(父类)找,最后去Object类找

    找不到会报错:java.lang.NoSuchFieldError

    如果找到但是没有权限(private):java.lang.illegalAccessError

    2.类方法的解析:

    class A extends B implements C,D{
    private void test(){
    ......
    }
    }

    在本类里面找有没有匹配的方法,如果没有前往父类找匹配的方法,没找到去接口列表里面找匹配的方法

    如果本类没找到,接口找到了,那么说明本类是:abstract抽象类

    如果最终没有找到报错:java.lang.NoSuchMethodError

    如果找到但是没有权限(private):java.lang.illegalAccessError

    3.接口方法的解析:

    在本类里面找有没有匹配的方法,然后在父接口中递归查找

    如果最终没有找到报错:java.lang.NoSuchMethodError

    接口一般不会是private,所以没有illegalAccessError

    第五步:初始化

    <init>类的初始化

    <clinit>静态变量,静态块的初始化;如果代码中没有静态变量和块,那么没有clint

    比如以下的代码中:

    class A{
     static int i=2;//clint
     static {//clint
       System.out.println("Hello World!");
     }
     int n;//init
    }

    第六步:使用

    无需解释

    第七步:卸载

    垃圾回收后面再学

    以上的验证,准备,解析三步又称为连接

  • 相关阅读:
    leetcode 202
    C++判断字符是否是元音字母
    [转][图]性能瓶颈分析图
    MySQL的一次优化记录 (IN子查询和索引优化)
    compiz隐藏最大化窗口标题栏
    hyper-v server 2019安装,工作组客户端远程管理
    powershell删除默认共享
    Powershell 更改计算机上的远程桌面的RDP端口
    Windows server 2019 Core安装Exchange 2019
    使用 PowerShell 安装 卸载Microsoft Defender 防病毒
  • 原文地址:https://www.cnblogs.com/xuyiqing/p/12466415.html
Copyright © 2011-2022 走看看