什么时候加载Java类? [英] When is a Java Class loaded?

查看:301
本文介绍了什么时候加载Java类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在互联网上搜索了超过几个小时,但无法得出任何结论。

I searched the internet for more than couple of hours and could not reach any conclusion.

最近我决定使用BouncyCastle进行SSL,但我希望它可以通过默认情况下,BouncyCastle jar可能不在类路径中。

Recently I decided to use BouncyCastle for SSL but I wanted it to off by default, so that BouncyCastle jar may not be in the class path.

private void enableBouncyCastleForSSL() {
   if (config.isBouncyCastleEnabled()) {
        Security.insertProviderAt(new BouncyCastleProvider(), 1);
    }
} 

即使配置被禁用,它也在寻找BouncyCastle并且它因类加载器错误而失败。 java.lang.NoClassDefFoundError:组织/ BouncyCastle的/ JCE /提供者/ BouncyCastleProvider

Even when config is disabled, it was looking for BouncyCastle and it failed with class loader error. java.lang.NoClassDefFoundError: org/bouncycastle/jce/provider/BouncyCastleProvider

我试图移动只是线Security.insertProviderAt(新BouncyCastleProvider(),1);对于一个新的方法,它表现出同样的问题。

I tried moving just the line Security.insertProviderAt(new BouncyCastleProvider(), 1); to a new method it exhibited the same problem.

但是当我引入一个类并在其中移动BouncyCastle时,当配置被禁用时,类加载器问题不会出现

But when I introduce a class and move the BouncyCastle inside it, when the config is disabled, class loader issue does not appear

private void setupSSLProvider() {
    if (voldemortConfig.isBouncyCastleEnabled()) {
        SetupSSLProvider.useBouncyCastle();
    }
}
public class SetupSSLProvider {
  public static void useBouncyCastle() {
    Security.insertProviderAt(new BouncyCastleProvider(), 1);
  }
}

有些文章声称Class只在它加载时加载第一次使用。 http:// www.programcreek.com/2013/01/when-and-how-a-java-class-is-loaded-and-initialized/

Some articles claim that Class is loaded only when it is first used. http://www.programcreek.com/2013/01/when-and-how-a-java-class-is-loaded-and-initialized/

显然在我的例子中,Java8加载类中引用的类。

Apparently in my case, Java8 loads the class referenced in a class.

所以我的理解是Java会在类中执行第一行代码之前加载一级深度的类。是吗?

So my understanding is Java will load the classes one level deep, before executing first line of code in a class. Is that right ?

推荐答案

这个问题没有简单的答案。规范为不同的实现策略留出了空间,甚至在一个实现中,它将依赖于如何使用该类。此外,您的问题更多的是什么时候可以失败,这取决于它可能失败的原因,例如:一个类可以在一个时间点加载以验证其存在,但是在实际首次使用时稍后初始化。在这两个时间点,操作可能会失败导致 NoClassDefFoundError

There is no simple answer to this question. The specification leaves room for different implementation strategies and even within one implementation, it will depend on how the class is been used. Further, your question is more about "when can it fail" which depends on why it may fail, e.g. a class may be loaded at one point of time to verify its existence but initialized at a later time when it is actually first‑time used. At both points of time, the operation may fail causing a NoClassDefFoundError.

我们可能会将引用的类分为三组:

We may categorize referenced classes into three groups:


  • 必须在连接时解析的类(例如超类)

  • 必须的类在验证时加载

  • 类的加载可以推迟到第一次实际使用

在您的情况下, BouncyCastleProvider 必须在验证时加载,而不是第一次实际使用,因为您传递的结果为 new BouncyCastleProvider()作为方法 Security.insertProviderAt(...)的参数,验证者必须检查该类是否实际扩展了提供者类型方法的形式参数要求的类型。

In your case, BouncyCastleProvider must be loaded at verification time, rather than its first actual use, because you are passing the result of new BouncyCastleProvider() as argument to the method Security.insertProviderAt(…) and the verifier must check whether the class actually extends the Provider type which the method’s formal parameter mandates.

当验证发生时,也是特定于实现的至少以下可能性允许:

When verification will happen, is also implementation specific as at least the following possibilities are allowed:


  • 在加载包含类或首次使用

  • 时,急切地遍历所有引用的类

  • 在执行违规指令之前,包含方法首次使用


  • eagerly traversing all referenced classes
  • on the loading of the containing class or its first use
  • on the containing method’s first use
  • right before executing the offending instruction

Oracle的JVM更喜欢方法的第一次使用,读取:在方法入口处验证它,因此,将调用移动到另一个不会执行的方法,无论是否在另一个类中,在您的情况下就足够了。

Oracle’s JVM prefers a method’s first use, read: verify it at the method entry, thus, moving the invocation into another method that won’t get executed, be it in another class or not, is sufficient in your case.

但要与其他JVM兼容,将其移动到另一个类更安全,但为了遵守所有可能的JVM,您甚至需要通过Reflection加载其他类以避免直接参考,可以通过一个热心执行遍历(或实例化 BouncyCastleProvider 反射性通过的Class.forName( ... .BouncyCastleProvider)。的newInstance()首先。)

But to be compatible with other JVMs, moving it into another class is safer, but to comply to all possible JVMs, you need to even load this other class via Reflection to avoid a direct reference that can be traversed by an eager implementation (or instantiate BouncyCastleProvider reflectively via Class.forName("… .BouncyCastleProvider").newInstance() in the first place).

这篇关于什么时候加载Java类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆