在java中动态加载Jar文件

时间:2014-12-07 16:42:01

标签: java jvm jit

我一直在阅读很多关于JIT和JVM的内容,我正在努力找出一些东西,希望有人可以提供帮助。

当我们编写包含外部JAR的java程序时, 例如: ExternalJar.jar包含:

ClassA.class
ClassB.class
ClassC.class

问题:

  1. 如果从未使用过JAR: 在初始化阶段(运行应用程序的JVM的第一阶段),JIT是否仍然会将JAR中包含的类编译为机器代码? 或者像DLL一样,只有当我们从JAR中的一个类实际调用一个方法时,JAR才会在运行时加载?

  2. 如果对1.的回答是我们实际从JAR中的一个类调用方法的时候: 那么使用JIT的好处是什么呢? JIT应该通过在应用程序启动阶段进行繁重的工作来改善运行时间。

  3. JIT是否必须编译JAR中的所有类,例如,如果我们使用:

    ClassB.MethodB();
    
  4. ClassA和ClassC也会被编译,因为它们在同一个JAR中吗?

    1. 包含基本java框架类的rt.jar怎么样: 例如,如果我打电话:

      System.out.println("");
      
    2. System.class是否也会被编译为机器代码(无论是在运行时启动还是在运行时实际调用该方法)或者是否存在某些已经缓存的这些类的机器代码?

      由于

2 个答案:

答案 0 :(得分:2)

在过去的经验中,JVM不会在需要之前尝试编译类。如果一个类引用另一个类,那么另一个类也将被编译。它位于类路径中的位置,Jar A或Jar B与编译无关。尽管在JVM中工作方式发生了长期变化,但我认为今天仍然如此。

像System这样的类是非常重要的,所以它们最终会被直接编译。 JVM的启动时间并不像许多人那样糟糕,但这并不意味着他们运行的应用程序具有良好的启动时间。

在传统的JIT(客户端VM)中,JVM只会执行已经编译过JIT的代码,并且不需要编译整个应用程序来开始执行(JIT代表Just in Time)。 JIT编译器生成了不错的可执行代码,但不是很好的可执行代码。

然后出现热点(服务器VM)。 JVM首先解释字节码,然后在运行时开始分析条件以确定要编译的内容。因为它不需要编译代码来运行它,所以它可以更快地开始执行,并且因为它不需要等待编译并且因为它知道运行时条件,所以它可以更加积极地进行优化。因此热点编译器产生更快的代码。缺点是,在开始时它执行得更慢,因为它正在执行解释代码。 Hotspot在编译后继续进行分析,因此可以通过更积极的优化再次编译被调用的方法(更热门的方法)。

很长一段时间,JVM默认在客户端模式下启动,您必须在服务器模式下显式启动它。有些JRE甚至没有提供服务器模式(例如windows),尽管他们相应的JDK也是如此。随着机器变得越来越强大,这已经没有意义了,所以JVM会使用一些启发式方法来确定它是应该在服务器模式还是客户端模式下启动。

然后,从Java 7开始,Oracle引入了混合模式。据我所知,允许它在开始时允许JIT编译代码(为了更好的启动性能),然后Hotspot会根据需要启动。

关于是否存在系统类的缓存。我认为他们在过去的某个时刻尝试过这个功能,但它并没有让事情变得更快,所以AFAIK不会发生这种情况。

修改的 看起来类共享仍然是一件事。 http://docs.oracle.com/javase/6/docs/technotes/guides/vm/class-data-sharing.html

答案 1 :(得分:0)

如果从未使用过JAR:JIT是否仍然会在初始化阶段(运行应用程序的JVM的第一阶段)将JAR中包含的类编译为机器代码?或者像DLL一样,只有当我们实际从JAR中的一个类调用一个方法时,才会在运行时加载JAR?

ANS:JAR仅在运行时加载,即使是JAR中的类也是在引用的类中第一次加载的。方法编译通常基于热点原理发生。

如果答案是1.当我们实际从JAR中的一个类调用一个方法时:那么使用JIT的好处是什么呢? JIT应该通过在应用程序启动阶段进行繁重的工作来改善运行时间。

ANS:JIT通常编译频繁使用的方​​法。这种大量使用是根据运行时信息确定的。 JIT剂量减少启动时间。

JIT是否必须编译JAR中的所有类,例如,如果我们使用:

ANS:没有

ClassB.MethodB(); ClassA和ClassC也会被编译,因为它们在同一个JAR中吗?

ANS NO

包含基本java框架类的rt.jar怎么样?例如,如果我调用:

的System.out.println("&#34); System.class是否也会被编译为机器代码(无论是在运行时启动还是在运行时实际调用该方法)或者是否存在某些已经缓存的这些类的机器代码?

ANS:NO,JIT仅编译高度使用的方法。它没有编译同一类中的所有其他方法。