Java 中的急切加载是啥?
Posted
技术标签:
【中文标题】Java 中的急切加载是啥?【英文标题】:What is eager loading in Java?Java 中的急切加载是什么? 【发布时间】:2019-10-30 23:36:46 【问题描述】:我在 Java 中遇到了 Spring NestedRuntimeException
和 AbstractApplicationContext
两个类中的即时加载,这两种情况都使用静态代码块解决了相同的类加载器问题,但是它们的使用方式令人困惑。
混淆是关于在静态代码块中调用ClassName.class.getName()
,这如何解决类加载器问题。
static
// Eagerly load the ContextClosedEvent class to avoid weird classloader issues
// on application shutdown in WebLogic 8.1. (Reported by Dustin Woods.)
ContextClosedEvent.class.getName();
如果我也这样做,我会得到类加载器并手动加载这个类
Thread.currentThread()
.getContextClassLoader().loadClass(ContextClosedEvent.class.getName());
我们将不胜感激任何专家的建议。
Reference
【问题讨论】:
"Eager" 只是意味着他们在真正需要之前加载类(通常 JVM 会在第一次使用时加载它)。他们在这里通过使用static
初始化程序来执行此操作,该初始化程序通过对其执行某些(无用的)操作来强制加载该类。它可能修复了类加载器问题,因为线程类加载器在第一次使用时懒惰地完成时可能会有所不同。但我同意你的看法,这是一个 hack。
我认为这个链接可以帮助你,获得一些知识https://***.com/a/2991015/6622913
仅供参考,在您的通话中,您将尝试加载同一个类两次。
@Thilo,这是有道理的,对方法的调用将加载类,使用线程的类加载器会抛出检查异常,他们可能希望在静态代码块中避免。
【参考方案1】:
在第一种情况下,如下例所示,ContextClosedEvent
将在使用 YourClass
时立即加载。
class YourClass
static
// Eagerly load the ContextClosedEvent class to avoid weird classloader issues
// on application shutdown in WebLogic 8.1. (Reported by Dustin Woods.)
ContextClosedEvent.class.getName();
第二种情况,ContextClosedEvent
会在你的代码运行时被加载,loadClass
方法会被调用2次。第一次是ContextClosedEvent.class
引用(由JVM调用),第二次是你手动调用。
第一次,ContextClosedEvent
实际上是从类路径加载的。第二次,取决于你的ContextClassLoader
。默认情况下,JVM的类加载器会findLoadedClass
而不是再次加载类。
如下例,loadClass
方法在运行时会调用两次main
。
class Main
public static void main(String[] args) throws ClassNotFoundException
Thread.currentThread()
.getContextClassLoader().loadClass(ContextClosedEvent.class.getName());
要查看静态块的工作原理,请运行此示例
class Main
public static void main(String[] args)
System.out.println("main method invoked");
static
System.out.println("static block invoked");
【讨论】:
正如你提到的findLoadedClass
在这里很重要,它不只是通过调用线程的类加载器(第二个 sn-p)来加载类,我使用 VM args -XX:+TraceClassLoading
确认了这一点以上是关于Java 中的急切加载是啥?的主要内容,如果未能解决你的问题,请参考以下文章
急切加载对 Laravel 中的模型事件/启动有一些意想不到的副作用