2009-11-25 24 views
27

我想提供有關正在使用哪些JAXP實現以及從哪個JAR文件加載的診斷信息。實現這一如何找出正在使用哪個JAXP實現以及它從哪裏加載?

一種方法是在實例創建,例如,DocumentBuilderFactory,然後檢查該類別的屬性:無需

private static String GetJaxpImplementation() { 
    DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); 
    Class<? extends DocumentBuilderFactory> c = documentBuilderFactory.getClass(); 
    Package p = c.getPackage(); 
    CodeSource source = c.getProtectionDomain().getCodeSource(); 
    return MessageFormat.format(
      "Using JAXP implementation ''{0}'' ({1}) version {2} ({3}){4}", 
      p.getName(), 
      p.getImplementationVendor(), 
      p.getSpecificationVersion(), 
      p.getImplementationVersion(), 
      source == null ? "." : " loaded from: " + source.getLocation()); 
} 

有沒有更好的方式來實現這一目標,也許創建一個DocumentBuilderFactory

回答

47

要預測什麼具體的JAXP工廠實現將被加載而不實際創建實例是非常困難的,因爲選擇實現的過程是非常困難的。

Official JAXP FAQ(問題14):

當應用程序要創建一個新的 JAXP DocumentBuilderFactory 情況下,它會調用staic方法 DocumentBuilderFactory.newInstance()。 這將導致使用 以下順序的 DocumentBuilderFactory一個 具體子類的名稱搜索:

  1. 系統屬性像javax.xml.parsers.DocumentBuilderFactory的值,如果它存在,並且可以訪問。
  2. 文件$JAVA_HOME/jre/lib/jaxp.properties的內容(如果存在)。
  3. Jar文件規範中指定的Jar服務提供程序發現機制。 jar文件可以具有包含要實例化的具體類的名稱的資源(即嵌入文件),例如META-INF/services/javax.xml.parsers.DocumentBuilderFactory
  4. 回退平臺的默認實現。

添加到這種複雜性,每個人JAXP工廠可以指定一個獨立的實現。通常使用一個解析器實現和另一個XSLT實現,但上面的選擇機制的粒度允許您混合和匹配更大的程度。

下面的代碼將關於四個主要JAXP工廠輸出信息:

private static void OutputJaxpImplementationInfo() { 
    System.out.println(getJaxpImplementationInfo("DocumentBuilderFactory", DocumentBuilderFactory.newInstance().getClass())); 
    System.out.println(getJaxpImplementationInfo("XPathFactory", XPathFactory.newInstance().getClass())); 
    System.out.println(getJaxpImplementationInfo("TransformerFactory", TransformerFactory.newInstance().getClass())); 
    System.out.println(getJaxpImplementationInfo("SAXParserFactory", SAXParserFactory.newInstance().getClass())); 
} 

private static String getJaxpImplementationInfo(String componentName, Class componentClass) { 
    CodeSource source = componentClass.getProtectionDomain().getCodeSource(); 
    return MessageFormat.format(
      "{0} implementation: {1} loaded from: {2}", 
      componentName, 
      componentClass.getName(), 
      source == null ? "Java Runtime" : source.getLocation()); 
} 

以下示例輸出示出的三個不同的JAXP實現(內置Xerces和混合和匹配外部JAR for Xerces 2.8和Xalan)一起工作:

DocumentBuilderFactory implementation: org.apache.xerces.jaxp.DocumentBuilderFactoryImpl loaded from: file:/C:/Projects/Scratch/lib/xerces-2.8.0.jar 
XPathFactory implementation: com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl loaded from: Java Runtime 
TransformerFactory implementation: org.apache.xalan.processor.TransformerFactoryImpl loaded from: file:/C:/Projects/Scratch/lib/xalan.jar 
SAXParserFactory implementation: org.apache.xerces.jaxp.SAXParserFactoryImpl loaded from: file:/C:/Projects/Scratch/lib/xerces-2.8.0.jar 
1

這取決於,但通常沒有。

DocumentBuilderFactory.newInstance()或者返回它在系統屬性「javax.xml.parsers.DocumentBuilderFactory中」或JRE的出廠默認設置,如果沒有設置系統屬性的DocumentBuilderFactory實施。默認的工廠很可能在newInstance方法的實現中被硬編碼,並且不可訪問。

如果設置了系統屬性,至少可以在相關的類加載器上使用getResource方法來獲取URL,類加載器將從中加載相應的類文件。如果它來自jar文件,則應該能夠從jar:URL中提取文件名(或源URL)。如果您從類路徑中手動讀取元數據文件,則還應提供詳細的軟件包信息。

如果沒有設置系統屬性,我很肯定你沒有辦法獲得你正在尋找的信息,而無需像你已經做的那樣實際創建一個新工廠。

1

還有另一個位置在「fallback platform defa ULT執行」,並且是java.endorsed.dirs目錄記錄在Java Endorsed Standards Override Mechanism

簽名標準覆蓋機制提供了一種方法,可將執行簽名標準或獨立技術的類和接口更高版本可以被合併到Java平臺。

+0

這是自8u40是BTW過時,你可以檢查它是否仍與'使用-XX:+ CheckEndorsedAndExtDirs'。 – eckes 2016-10-31 16:46:22

2

很容易,你只要設置

System.setProperty("jaxp.debug", "1"); 

軌道會告訴你whick IMPL和whick方式JAXP使用。

相關問題