本文主要是介绍【Java ClassLoader】类加载循环依赖问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
示例1:匿名内置类
public class LazyDemo {private static boolean initialized = false;// LazyDemo static模块执行时(类还未完全初始化),Runnable 匿名内置类随之初始化// 如果Runnable匿名内置类依赖了外部对象,就会导致类加载时出现循环等待,产生死锁static {print("static 模块执行!");// Case 1 匿名内置类:(不能运行)// 如果是匿名内内置类(LazyDemo$1.class)的话,它的类初始化依赖于外部类初始化Thread t1 = new Thread(new Runnable() { @Overridepublic void run() {// Runnable类依赖了LazyDemo类中的对象,产生了循环等待,导致死锁情况。initialized = true;}});t1.start();try {t1.join();} catch (InterruptedException e) {e.printStackTrace();}}public static void main(String[] args) {print("main 执行!");System.out.println(initialized);}private static void print(Object obj) {System.out.printf("线程执行:[%s] - %s", Thread.currentThread().getName(), obj);}
}
运行结果: 死锁不动了!
字节码指令:
示例2:lambdas表达式语法
public class LazyDemo {private static boolean initialized = false;static {print("static 模块执行!");// Case 2 lambdas表达式:invokedynamic指令实现(不能运行)// lambdas语法是为了代替以前的匿名内部类,但是lambdas表达式实现方式和匿名内置类不一样,是用invokedynamic实现。// LazyDemo static模块执行时(类还未完全初始化)lambdas表达式随之初始化// 此lambdas语法会成为LazyDemo字节码指令的一部分,但该指令的完成又依赖于整个类的完成,就会导致类加载时出现循环等待,产生死锁Thread t1 = new Thread(() -> {});t1.start();try {t1.join();} catch (InterruptedException e) {e.printStackTrace();}}public static void main(String[] args) {print("main 执行!");System.out.println(initialized);}private static void print(Object obj) {System.out.printf("线程执行:[%s] - %s", Thread.currentThread().getName(), obj);}
}
运行结果: 死锁不动了!
字节码指令:
示例3:方法引用
public class LazyDemo {private static boolean initialized = false;static {print("static 模块执行!");// Case 3 方法引用:invokedynamic指令实现(能够运行)// System.out::println:方法属于System.out对象类java.io.PrintStream,它被Bootstrap ClassLoader加载// 早于LazyDemo.class的APP ClassLoader加载Thread t1 = new Thread(System.out::println);t1.start();try {t1.join();} catch (InterruptedException e) {e.printStackTrace();}}public static void main(String[] args) {print("main 执行!");System.out.println(initialized);}private static void print(Object obj) {System.out.printf("线程执行:[%s] - %s", Thread.currentThread().getName(), obj);}
}
运行结果: 正常执行完了!
字节码指令:
感谢阅读,下次再见。ヾ( ̄▽ ̄)ByeBye!
这篇关于【Java ClassLoader】类加载循环依赖问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!