Java 中的急切加载是啥?

Posted

技术标签:

【中文标题】Java 中的急切加载是啥?【英文标题】:What is eager loading in Java?Java 中的急切加载是什么? 【发布时间】:2019-10-30 23:36:46 【问题描述】:

我在 Java 中遇到了 Spring NestedRuntimeExceptionAbstractApplicationContext 两个类中的即时加载,这两种情况都使用静态代码块解决了相同的类加载器问题,但是它们的使用方式令人困惑。

混淆是关于在静态代码块中调用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 Eloquent 中的急切加载

远程案例中的延迟/急切加载策略(JPA)

LINQ中的First()会导致急切或延迟加载吗?

急切加载对 Laravel 中的模型事件/启动有一些意想不到的副作用

TypeORM postgresql 急切加载关系定义为惰性

Sequelize 急切加载错误