【深入浅出-JVM】(75):class 装载

本文深入探讨Java类加载机制,包括装载、连接、初始化各阶段的细节,以及类的主动使用与被动引用的区别。通过具体代码示例,阐述类加载过程中触发类初始化的条件,并分析常量与静态字段在类加载中的作用。

过程

装载

条件

主动使用 class时

  • 创建一个类的实例 (new 、反射、克隆、反序列化)
  • 调用类的静态方法(invokestatic)
  • 使用类或接口的静态字段(getstatic、putstatic)
  • 使用 reflect反射
  • 初始化子类,先初始化父类
  • main方法的类

例子

被动引用不会初始化类

package com.mousycoder.mycode.thinking_in_jvm;

/**
 * @version 1.0
 * @author: mousycoder
 * @date: 2019-09-02 16:29
 */
public class Parent {
    static {
        System.out.println("Parent init");
    }
    public static int v = 100;
}



package com.mousycoder.mycode.thinking_in_jvm;

import sun.jvm.hotspot.memory.ParNewGeneration;

/**
 * @version 1.0
 * @author: mousycoder
 * @date: 2019-09-02 16:29
 */
public class Child extends Parent {

    static {
        System.out.println("Child init");
    }
}

package com.mousycoder.mycode.thinking_in_jvm;

/**
 * @version 1.0
 * @author: mousycoder
 * @date: 2019-09-02 16:32
 */
public class UseParent {
    public static void main(String[] args) {
        System.out.println(Child.v);
    }
}

虚拟机参数 -XX: TraceClassLoading输出

[Loaded com.mousycoder.mycode.thinking_in_jvm.Parent from file:/Users/mousycoder/My/code/mycode/target/classes/]
[Loaded com.mousycoder.mycode.thinking_in_jvm.Child from file:/Users/mousycoder/My/code/mycode/target/classes/]
Parent init
100
[Loaded java.lang.Shutdown from /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.lang.Shutdown$Lock from /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/lib/rt.jar]

表示 Child被加载了,但是没有被初始化

final 常量不会引起类初始化

package com.mousycoder.mycode.thinking_in_jvm;

/**
 * @version 1.0
 * @author: mousycoder
 * @date: 2019-09-02 16:41
 */
public class FinalFieldClass {

    public static final String constString = "CONST";
    static {
        System.out.println("FinalFieldClass init");
    }


}
package com.mousycoder.mycode.thinking_in_jvm;

public class UseFinalField {
    public static void main(String[] args) {
        System.out.println(FinalFieldClass.constString);
    }
}

输出

CONST

FinalFieldClass 类没有因为常量 constString 被引用而初始化,而是直接把CONST 放在常量池中

加载

例子:加载String类

package com.mousycoder.mycode.thinking_in_jvm;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * @version 1.0
 * @author: mousycoder
 * @date: 2019-09-03 13:38
 */
public class StringTest {
    public static void main(String[] args) throws ClassNotFoundException {
        Class clzStr = Class.forName("java.lang.String");
        Method[] ms = clzStr.getDeclaredMethods();
        for (Method m : ms) {
            String mod = Modifier.toString(m.getModifiers());
            System.out.println(mod   " "   m.getName()   " ( ");
            Class<?>[] ps = m.getParameterTypes();
            if (ps.length == 0 ){
                System.out.println(')');
            }
            for (int i = 0; i < ps.length; i  ) {
                char end =i==ps.length-1 ? ')':',';
                System.out.println(ps[i].getSimpleName()   end);
            }
            System.out.println();
        }
    }
}

输出public equals (Object)

public toString ()

public hashCode ()

public volatile compareTo (Object)

public compareTo (String)

public indexOf (String,int)`

验证

保证加载的字节码合法

准备

为类分配对应的内存空间,并设置初始值,此阶段不会有 java 代码执行

类型默认初始值
int0
long0L
short(short)0
charu0000
booleanfalse
referencenull
float0f
double0f

解析

将类、接口、字段、方法的符号引用(字面量的引用)转成直接引用(找到方法中表的位置)

初始化

执行类的初始化方法 ,此方法由编译器自动生成的,由类静态成员的赋值语句以及static 语句块合并产生其中 函数是带锁线程安全的,可能会导致死锁。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值