Jave 如何防止并发类初始化发生?

Par*_*olu 2 java jvm class

java 类在每个 JVM 中仅在首次加载时初始化一次。而且我认为多个线程可以尝试同时加载同一个类。JVM 如何处理这种争用?有没有什么机制可以防止这种情况发生,比如锁?

Mur*_*nik 5

首先,以下说法不准确:

每个 jvm 中的 java 类仅初始化一次

每个类加载器都会初始化一个 Java 类一次。一个 JVM 实例很可能有多个类加载器,每个类加载器分别加载同一个类。

为了回答这个问题 - 是的,类加载器在加载类时必须锁定。例如,如果您看一下 OpenJDK 9 的实现java.lang.ClassLoader,加载类最终将归结为以下方法(添加注释以强调锁定):

final Class<?> loadClass(Module module, String name) {
    synchronized (getClassLoadingLock(name)) { // Note the locking here!
        // First, check if the class has already been loaded
        Class<?> c = findLoadedClass(name);
        if (c == null) {
            c = findClass(module.getName(), name);
        }
        if (c != null && c.getModule() == module) {
            return c;
        } else {
            return null;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 从 JVM 的角度来看,“多个类加载器,每个类加载器分别加载相同的类”只是定义*不同*类的几个类加载器,即使它们可能具有相同的名称甚至相同的字节码。因此,“一个 java 类在每个 jvm 中只初始化一次”这一说法是正确且准确的。除此之外,引用的代码仅实现类的*加载*,而不是*初始化*。确保初始化只发生一次仍然由 JVM 负责。 (3认同)