ZipFile.getEntry()SAXParserFactory.newInstance() → FactoryFinder.find() → ClassLoader.getResourceAsStream() → JarURLConnection → ZipFile.getEntry()javax.xml.parsers.FactoryFinder.find() 依序嘗試:
-Djavax.xml.parsers.SAXParserFactory=xxx$JAVA_HOME/lib/jaxp.properties 指定實作類META-INF/services/javax.xml.parsers.SAXParserFactory — 此步驟需掃描 JAR 檔 (ZipFile.getEntry)org.apache.xerces.jaxp.SAXParserFactoryImpl (在當前 ClassLoader 查找)客戶環境前三條件均不滿足,每次解析 XML 皆走到第 3 步,**重複掃描 xerces.jar 的 META-INF 目錄**,導致大量執行緒在 ZipFile.getEntry() 同步鎖上爭用,形成效能瓶頸。
-Djavax.xml.parsers.SAXParserFactory=your.impl.Class$JAVA_HOME/lib/ 建檔,寫入 javax.xml.parsers.SAXParserFactory=your.impl.ClassThread Dump 顯示:GenericClassLoader.loadClass() → FactoryFinder.newInstance() → find(),大量執行緒阻塞於 WebLogic 類別載入器鎖。
ClassLoader.loadClass() 預設實作邏輯:
findLoadedClass() — 檢查已載入快取loadClass()findClass() — 實際查找定義堆疊顯示的「大量 loadClass」多半是 **快取查找 (findLoadedClass) 失敗後的父載入器委派**,非真正重複載入類別。WebLogic 階層式 ClassLoader (應用 → 模組 → 系統) 導致委派鏈較長,鎖競爭顯著。
loadClass 阻塞時,優先檢查 SPI 機制與 ClassLoader 階層// FactoryFinder.find() 關鍵邏輯
static Object find(String factoryId, String fallbackClassName) {
// 1. System Property
String systemProp = System.getProperty(factoryId);
if (systemProp != null) return newInstance(systemProp, classLoader);
// 2. jaxp.properties
File configFile = new File(System.getProperty("java.home") + "/lib/jaxp.properties");
if (configFile.exists()) { /* 載入屬性檔 */ }
// 3. META-INF/services/ (SPI) — 會開啟 JAR 檔
String serviceId = "META-INF/services/" + factoryId;
InputStream is = classLoader.getResourceAsStream(serviceId); // 這裡觸發 ZipFile.getEntry
if (is != null) { /* 讀取實作類名 */ }
// 4. Fallback
return newInstance(fallbackClassName, classLoader);
}
// ClassLoader.loadClass() 標準實作
protected synchronized Class> loadClass(String name, boolean resolve) {
Class> c = findLoadedClass(name); // 快取查找
if (c == null) {
try {
if (parent != null) c = parent.loadClass(name, false);
else c = findBootstrapClassOrNull(name);
} catch (ClassNotFoundException e) {
c = findClass(name); // 真正查找
}
}
if (resolve) resolveClass(c);
return c;
}