通过向classes.jsa添加自己的应用程序类来加速应用程序启动

时间:2011-01-14 14:29:51

标签: java jvm startup jsa

为了加快JVM的启动时间,Sun开发人员认为在安装JVM期间为平台预编译标准运行时类是个好主意。可以找到这些预编译的类,例如于:

$ JAVA_HOME \ JRE \ BIN \客户\ classes.jsa

我公司目前正在开发一个Java独立应用程序,它带来了自己的JRE,因此通过在这个jsa文件中添加我们自己的应用程序类来加速我们的应用程序启动时间是一个很棒的选择。

我不相信JSA文件是由魔法创建的,所以:它是如何创建的?我如何欺骗JVM合并我自己的类?

编辑:我已经发现了以下内容:

classes.jsa由命令

创建
java -Xshare:dump

可以在$JAVA_HOME/jre/lib/classlist中找到要合并到转储中的类列表。

我甚至设法在这里添加我自己的类(并将它们添加到rt.jar中以便java找到它们),并在classlist文件下面生成我自己的校验和。

最后一个问题是:只有java,com.sun和org.w3c包中的类似乎被识别,如果我在原始包中保留相同的类,它们将不会被加载。我在整个OpenJDK源代码中搜索了这个指针,但它似乎与保护域有关。如果有人对这个主题感兴趣并且知识渊博,请为我提供一些指导,以便进一步调查。

4 个答案:

答案 0 :(得分:11)

你几乎就在那里,你只需要几个步骤就能让它发挥作用。要将自己的类添加到clients.js,您需要执行以下步骤:

  1. 您的课程的合格名称(您拥有)

  2. 这些类的类路径(你有)

  3. 知道如何重新计算校验和(你有)

  4. 转储新文件,提供您现在使用Java类预编译的类的类路径。

  5. 运行程序,提供与转储新类相同的类路径.jsa

  6. 要提供类路径,您要将类添加到类列表中,请使用-Xbootclasspath/a命令。当JVM搜索引导类所在的位置时,它将附加目录/ JAR。 classes.jsa的默认空间非常小,如果需要改进它,可以使用-XX:SharedReadWriteSize-XX:SharedReadOnlySize命令。您的转储命令看起来与此类似:

    java -Xshare:dump -Xbootclasspath/a:C:/myfiles/directoryA/;C:/myfiles/directoryB/;C:/myJars/myJar.jar;
    

    最后一步是正常运行java应用程序,重新开启共享模式。您还需要在转储时添加Xbootclasspath。它看起来与此类似:

    java myapp.java -Xshare:on -Xbootclasspath/a:C:/myfiles/directoryA/;C:/myfiles/directoryB/;C:/myJars/myJar.jar;
    

    现在,您放在类列表中的每个类都与在同一JVM中运行的其他实例共享。

答案 1 :(得分:11)

从Java 8u40(和嵌入式Java 8u51)开始,Java现在支持应用程序类数据共享(AppCDS)(即您在共享存档中的类)。在我们的嵌入式java上,我们发现启动改进率> 40%!对我们来说几乎没有工作非常棒......

https://blogs.oracle.com/thejavatutorials/entry/jdk_8u40_released

答案 2 :(得分:8)

有趣的想法。正如我读到的那样,它用于跨VM共享数据和加速类加载,而不是编译。我不确定你会得到多大的提升,但如果你在启动时已经有很大的延迟(尽管VM已经试图减轻这种情况),那么它可能值得一试。

至于自己尝试,看起来这个文件通常在安装Sun VM时创建,但您也可以控制它。有些详细信息在旧的Sun Java 5 Class Data Sharing文档中(您可能已经看过了吗?)。某些Sun Java 6文档也mention it a few times,但不会对文档添加太多内容。它似乎最初是IBM VM feature。并且,为了继续链接转储,它解释了一点in this article

我个人对此并不了解,所以我不知道你怎么控制它。你可以重新生成它,但我认为你不打算将自定义内容放入其中。此外,即使您可以“欺骗”它,也可能违反某种类型的Sun / Oracle许可证(例如,您不能乱用rt.jar和重新分发)。而且,所有这一切,我怀疑你会看到启动时间的严重改善,除非你的应用程序中有成千上万的课程?

(这不是一个真正的答案,我知道,但它太大了,不适合评论,我发现这个问题很有趣所以我调查了一下,并把链接放在这里以防万一有人发现相同的信息有用。)

答案 3 :(得分:0)

我花了一点时间搞清楚,但我有4个使用共享类运行的Java8 VM(版本1.8.0_162)。以下脚本用于设置和测试共享,稍作修改即可在其他地方使用:

#!/bin/bash

# Libraries to load
LIBS1="./lib/protobuf-java-2.6.1.jar:\
./lib/jetty-server-9.2.18.v20160721.jar:./lib/jetty-util-9.2.18.v20160721.jar:./lib/servlet-api-3.1.jar:./lib/jetty-http-9.2.18.v20160721.jar:./lib/jetty-io-9.2.18.v20160721.jar:\
./lib/derby.jar:\
./lib/json-simple-1.1.1.jar:"
LIBS2=":./lib/GTFS.jar"

# Uncomment these lines for the first phase where you are determining the classes to archive. During this phase aim to get as many classes loaded as possible
# which means loading a schedule and retrieving the stop list and next vehicle information
#
#APPCDS="-Xshare:off -XX:+UnlockCommercialFeatures -XX:+UseAppCDS -XX:DumpLoadedClassList=../GtfsAppCds.lst"
#java -Xmx512m $APPCDS -Dderby.system.home=database -classpath $LIBS1$LIBS2 com.transitrtd.GtfsOperatorManager

# Uncomment these lines when the class list is created and run to create the shared archive. Classes marked as unverifiable will need to be removed from the
# archived class list in GtfsAppCds.lst and the lines below run again. LIBS2 above contains jars which are left out of the archive. These are jars which change
# frequently and would therefore cause the archive to be frequently rebuilt.
#                                                                                                                                                                                                               
#APPCDS="-Xshare:dump -XX:+UnlockCommercialFeatures -XX:+UseAppCDS -XX:SharedClassListFile=../GtfsAppCds.lst -XX:SharedArchiveFile=../GtfsAppCds.jsa"
#java -Xmx512m $APPCDS -classpath $LIBS1

# Uncomment these lines when wishing to verify the application is using the shared archive.
#
#APPCDS="-Xshare:on -XX:+UnlockCommercialFeatures -XX:+UseAppCDS -XX:SharedArchiveFile=../GtfsAppCds.jsa -verbose:class"
#java -Xmx512m $APPCDS -Dderby.system.home=database -classpath $LIBS1$LIBS2 com.transitrtd.GtfsOperatorManager

请注意,共享存档文件(即jsa文件)取决于体系结构,需要在每种目标平台类型上构建。

如果jar使用密封包,则抛出安全异常,请参阅

prefetch

有关密封包装的信息。上面是 derby.jar 的情况,但问题可以通过解压缩jar文件来解决,用密封替换密封:真:假在清单中并重新包装它。

使用旧版本的java构建的jar不能在共享存档中使用,在上面的情况下需要将derby版本从10.10升级到10.14才能获益。