吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4420|回复: 16
收起左侧

[Java 转载] JVM核心机制

  [复制链接]
iceflow 发表于 2018-10-24 08:48

JVM核心机制

类加载过程

JVM 把 class 文件加载到内存,并对数据进行校验,解析和初始化,最终形成 JVM 可以直接使用的 JAVA 类型的过程。

将Java类的二进制代码合并到JVM运行状态之中的过程

  • 验证:确保加载的类信息符合JVM规范,没有安全方面的问题。  

  • 准备:正式为类变量 static 变量分配内存并设置类变量初始值的阶段,这些内存都将在方法区中进行分配。

  • 解析:虚拟机常量池内的符号引用替换为直接引用的过程。

  所谓常量池的符号引用 例如创建一个新的类:
  public class MyClass {
      public static void main(String[] args) {
          String str = "abv";
          int i = 5;
      }
  }
这里面的 `MyClass` `str`  `i` 都可以说是常量 存放于常量池中

初始化

  • 初始化阶段是执行类构造器clinit()方法的过程,类构造器clinit()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块static块中的语句并合并产生的。

    <font color=red>clinit() 方法平时我们是看不到的,而且也不能自己去定义它</font>

  • 当初始化一个类的时候,如果发现其父类还没有进行初始化、则需要先出发其父类的初始化。
  • 虚拟机会保证一个类的 clinit() 方法在多线程环境中被正确的加锁和同步。

    当一个类被初始化的时候肯定是线程安全的

  • 当访问一个 Java 类静态域的时候,只有真正声明这个域的类才会被初始化。

    例图
    JVM用例图.png                                           

    /**
    * Created by BF on 2017/9/14.
    * 了解JVM加载类全过程
    */
    public class demo01 {
    public static void main(String[] args) {
    // 当A对象被创建的时候 先会执行静态代码块,再实执行A的构造方法
    A a = new A();
    System.out.println(a.width);
    // 输出顺序为  创建初始化类A--> width = 300 --> 创建A对象
    }
    }
    class A {
    public static int width = 100;
    static {
    System.out.println("静态初始化类A");
    width = 300;
    }
    public A(){
    System.out.println("创建A对象");
    }
    }

加载

  • 将 class 文件字节码内容加载到内存中,并将这些静态数据转换成方法 区中的运行时数据结构,在堆中生成一个代表这个类的 java.lang.Class 对象,作为方法区类数据的访问入口,<font color=red>这个过程需要类的加载器参与</font>。

  • 类加载全过程  --><font color=gray>重点理解</font>
    便于理解,先把代码贴出来

    public class demo01 {
      public static void main(String[] args) throws ClassNotFoundException {
        // 主动引用
        new A();
        System.out.println(A.width);
        Class.forName("com.wiceflow.JVM.A");
        // 被动引用
        System.out.println(A.MAX);
        A[] as = new A[10];
        System.out.println(B.width);
      }
    }
    
    class A extends A_Father{
      public static int width = 100;
      public static final int MAX = 200;
      static {
        System.out.println("静态初始化类A");
        width = 300;
      }
    
      public A(){
        System.out.println("创建A对象");
      }
    }
    class A_Father{
      static {
        System.out.println("静态初始化A的父类");
      }
    }
    class B extends A{
      static {
        System.out.println("静态初始化类B");
      }
    }
    new A() 正常打印结果:
      静态初始化A的父类
      静态初始化类A
      创建A对象
    • 类的主动引用(一定会发生类的初始化)

      • new 一个类的对象

        >当new一个类的新对象,类必然会初始化 eg:new A()

      • 调用类的静态成员(除了final常量)和静态方法

        >eg:上述类A中有静态成员 width 当在其他类中调用到 A.width,类A一定会初始化

      • 使用java.lang.reflect包的方法对类进行反射调用

        >放射调用该类必会导致该类初始化,否则反射调用不会成功 eg: Class.forName("com.wiceflow.JVM.A")

      • 当虚拟机启动,java Hello,则一定会初始化Hello类,说白了就是启用Main方法所在的类

      • 当初始化一个类,如果其父类没有被初始化,则会先初始化其父类

        >由上述代码可以看出 A类继承A_Father类,当A类初始化的时候,因为其继承了A_Father,所以会先初始化A_Father类,而每个类都会继承Object类,所以这个类一定会被初始化

    • 类的被动引用(不会发生类的初始化)

      • 当访问一个静态域时,只有真正声明这个域的类才会被初始化

        • <font color=“”>通过子类引用父类的静态变量,不会导致子类初始化</font>
          >例如上面类B继承了类A,当B中调用B.width的时候,由于类B本身没有width变量,所以是取自其父类A,这时候虚拟机初始化的是类A,而类B并不会被初始化
      • 引用常量不会触发此类的初始化(常量在编译阶段就存入调用类的常量池中了)
        >eg:在A中定义了一个final常量MAX,这个常量在编译的时候就会创建并存储在方法区(特殊的堆)中,这时候调用只是在方法区将其取出,并不会涉及类A的初始化

免费评分

参与人数 3吾爱币 +7 热心值 +3 收起 理由
薏苡仁 + 1 + 1 用心讨论,共获提升!
冼星海ksv + 1 + 1 JAVA天下第一!
苏紫方璇 + 5 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| iceflow 发表于 2018-10-24 14:33
butz110 发表于 2018-10-24 14:10
楼主讲的第一个实例是不是不对啊?打印的结果不是  // 输出顺序为  创建初始化类A--> width = 300 --> 创建 ...

你的是正确的,这里我忘记改了
butz110 发表于 2018-10-24 14:10
楼主讲的第一个实例是不是不对啊?打印的结果不是  // 输出顺序为  创建初始化类A--> width = 300 --> 创建A对象
应该是下面的吧!

静态初始化类A
创建A对象
300
 楼主| iceflow 发表于 2018-10-24 08:49
海水不见深蓝 发表于 2018-10-24 09:21
节..节日快乐~~~紫薯布丁
cosla 发表于 2018-10-24 09:29
膜拜大神
ozinne 发表于 2018-10-24 09:47
楼主几年java开发。
waipojie123 发表于 2018-10-24 11:01
支持一下
薏苡仁 发表于 2018-10-24 11:23
大佬还会更新吗
butz110 发表于 2018-10-24 11:49
学习了,这个确实有难度的
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-26 01:39

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表