JVM成神之路-类加载机制-双亲委派,破坏双亲委派( 三 )


static class Parent{public static int A=1;static{A=2;}}static class Sub extends Parent{public static int B=A;}public class Test{public static void main(String[] args){System.out.println(Sub.B);}}
public class DealLoopTest {static class DeadLoopClass {static {if (true)// 如果不加上这个if语句,编译器将提示“Initializer does not complete normally”错误{System.out.println(Thread.currentThread() + "init DeadLoopClass");while (true) {}}}}public static void main(String[] args) {Runnable script = new Runnable() {public void run() {System.out.println(Thread.currentThread() + " start");DeadLoopClass dlc = new DeadLoopClass();System.out.println(Thread.currentThread() + " run over");}};Thread thread1 = new Thread(script);Thread thread2 = new Thread(script);thread1.start();thread2.start();}}
运行结果:(即一条线程在死循环以模拟长时间操作,另一条线程在阻塞等待)
Thread[Thread-1,5,main] startThread[Thread-0,5,main] startThread[Thread-1,5,main]init DeadLoopClass
需要注意的是,其他线程虽然会被阻塞,但如果执行()方法的那条线程退出()方法后,其他线程唤醒之后不会再次进入()方法 。同一个类加载器下,一个类型只会初始化一次 。
将上面代码中的静态块替换如下:
static {System.out.println(Thread.currentThread() + "init DeadLoopClass");try {TimeUnit.SECONDS.sleep(10);}catch (InterruptedException e) {e.printStackTrace();}}
运行结果:
Thread[Thread-0,5,main] startThread[Thread-1,5,main] startThread[Thread-0,5,main]init DeadLoopClassThread[Thread-0,5,main] run overThread[Thread-1,5,main] run over
原因在类加载-时机的主动引用中已经解释了 。
类加载器(class )
概念
类加载器(class )用来加载 Java 类到 Java 虚拟机中 。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件) 。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例 。每个这样的实例用来表示一个 Java 类 。通过此实例的 ()方法就可以创建出该类的一个对象 。
类加载器应用在很多方面,比如类层次划分、OSGi、热部署、代码加密等领域 。
基本上所有的类加载器都是 java.lang.类的一个实例
java.lang.类
java.lang.类的基本职责就是根据一个指定的类的名称,找到或者生成其对应的字节代码,然后从这些字节代码中定义出一个 Java 类,即 java.lang.Class类的一个实例 。除此之外,还负责加载 Java 应用所需的资源,如图像文件和配置文件等 。
为了完成加载类的这个职责,提供了一系列的方法
方法
说明
()
返回该类加载器的父类加载器 。
( name)
加载名称为name的类,返回的结果是java.lang.Class类的实例 。
( name)
查找名称为name的类,返回的结果是java.lang.Class类的实例 。
( name)
查找名称为name的已经被加载过的类,返回的结果是java.lang.Class类的实例 。
( name, byte[] b, int off, int len)
把字节数组 b中的内容转换成 Java 类,返回的结果是 java.lang.Class类的实例 。这个方法被声明为final的 。
(Class c)
链接指定的 Java 类 。
类与类加载器
类加载器虽然只用于实现类的加载动作,但它在java程序中起到作用却远远不限于类加载阶段 。对于任意一个类,都需要由加载它的类加载器和这个类本身一起确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间 。(比较两个类是否相等,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则即使这两个类来源于同一个Class文件,被同一个虚拟机加载,只要加载它们的类加载器不同,那这两个类肯定不会相等)