【问题标题】:JAXBContext initialization speedup?JAXBContext 初始化加速?
【发布时间】:2010-10-22 02:46:53
【问题描述】:

有没有什么方法可以加快 javax.xml.bind.JAXBContexts 的初始化以及大量(>1000)类的初始化?在我们的 XML 繁重的应用程序中,启动时间大约为 10 分钟,主要包括 JAXBContexts 的初始化时间。 :-(

我们在 JDK 1.5 中使用 Sun 的 JAXB 实现,并使用 org.jvnet.jaxb2.maven2.maven-jaxb2-plugin 从 XSD 生成代码。

澄清:问题不在于我们有许多具有相同上下文路径的 JAXBContext 实例,而在于一个 JAXBContext 的初始化需要数十秒,因为它必须加载和处理数千个类。 (我们的 XSD 相当大且复杂。)所有 JAXBContext 实例都有不同的上下文路径 - 我们无法进一步减少数量。

【问题讨论】:

    标签: java performance jaxb


    【解决方案1】:

    出于这个原因,JAXB 参考实现具有某种未记录的系统属性:

    -Dcom.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.fastBoot=true
    

    或者对于包重构之前的旧版本:

    -Dcom.sun.xml.bind.v2.runtime.JAXBContextImpl.fastBoot=true
    

    这指示 JAXB 跳过预先缓存完成这项工作所需的各种反射肌肉的昂贵过程。相反,它会在使用上下文时进行所有反射。这会导致运行时间变慢,但初始化速度要快得多,尤其是对于大量类。

    然而,速度问题的一部分是不可避免的,那就是 JAXB 必须加载每个类,并且类加载很慢。如果您在第一个上下文之后立即使用相同的配置创建第二个上下文,则这一点很明显 - 您会发现它已经加载了类要快得多。

    另外,您说您有多个 JAXBContext 实例,因为您有多个上下文路径。您是否意识到可以将多个上下文路径放入单个上下文中?您只需在初始化上下文时将它们全部作为分号分隔的字符串传递,例如

    JaxbContext.newInstance("a.b.c:x.y.z");
    

    将加载上下文a.b.c 和x.y.z。不过,它可能不会对性能产生任何影响。

    【讨论】:

    • 为了澄清,您需要使用冒号来分隔包名,而不是分号。至少对于 Sun JAXB RI。
    • -Dcom.sun.xml.bind.v2.runtime.JAXBContextImpl.fastBoot=true 不适用于旧实现,如果您使用 glassfish jaxb-runtime 2.3.3(最流行的之一) ,属性为-Dcom.sun.xml.bind.v2.runtime.JAXBContextImpl.fastBoot=true
    • 如有疑问,请参阅您正在使用的 JaxbContextImpl 的包。那个包是正确的。引用代码:fastB = Boolean.getBoolean(JAXBContextImpl.class.getName()+".fastBoot");
    【解决方案2】:

    通常,您不必创建许多 JAXBContext 实例,因为它们在配置后是线程安全的。在大多数情况下,只需一个上下文就可以了。

    那么创建许多实例是否有特定原因?也许有人假设它们不是线程安全的? (这是可以理解的,因为没有明确记录——但这是一种非常常见的模式,需要在配置期间同步,但在使用期间不需要同步,只要不更改配置即可)。

    除此之外,如果这仍然是一个问题,则在 jaxb.dev.java.net 上分析瓶颈并提交问题(从配置文件中指出热点)将有助于改善问题。 JAXB 团队非常优秀,反应迅速,如果您能指出问题出在哪里,他们通常会提出很好的解决方案。

    【讨论】:

    • 看问题中的说明:每个实例都有不同的上下文路径,所以我们不能减少实例的数量。问题是这些单个实例的初始化需要几十秒。
    • 好的。仍然好奇是否有可能创建一个静态引用依赖类的虚拟“根类”,以允许仅构造一个超上下文。但可能还有其他理由不这样做。如果您确实有时间,我建议您真正进行简单的分析,看看时间花在了哪里。只要任何一个上下文的创建速度很慢,使用常规 JVM 和 -Xhprof 运行,您就应该在堆栈跟踪中看到一些罪魁祸首。这可能暗示一种解决方法,或指出 JAXB 团队进行改进。
    • @hstoerr 因为初始化过程大约需要 10 秒,所以在应用程序启动时并行执行初始化过程不是最实用的吗?
    【解决方案3】:

    JAXBContext 确实是线程安全的,因此建议使用单例包装它。我写了一个简单的单例,其中包含一个似乎可以完成这项工作的类->上下文映射。如果您的应用程序使用许多线程,您可能还想创建一个 [un]marshaller 对象池,因为这些对象不是线程安全的,并且您也可能会看到一些初始化惩罚。

    【讨论】:

    • 见我的澄清 - 这没有帮助。
    • 如果初始化一个 Context 需要这么长时间,那么您可能无法像 StaxMan 建议的那样分析 JAXB 代码本身。假设它不是一个长时间运行的应用程序,初始化时间可能会被忽略,你可能想看看其他 ORM,尽管我不确定在这方面有没有更好。
    【解决方案4】:

    在我们的例子中,更新 JAXB 库是一个好主意。顺便说一句,即使在开发环境中使用服务器 VM 代替客户端 VM 也是一个好主意,尽管它通常会减慢服务器启动速度:由于 JAXB 初始化需要很长时间,因此更好地编译服务器 VM 会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-30
      • 2023-03-08
      相关资源
      最近更新 更多