openfire 部署後報錯: java.lang.IllegalArgumentException: interface xx is not visible from class loader

不知為何就叫呵呵發表於2017-12-01

該異常是建立代理時載入介面的類載入器與建立時傳入的不一致。

在本地eclipse做openfire二次開發,本地執行沒錯,部署到伺服器上後報異常:

     java.lang.IllegalArgumentException: interface xx is not visible from class loader。

根據異常資訊,可知是動態代理時出錯的。而在之前部署過卻沒有這異常發生。

從日誌上分析,可以找到拋異常的地方是:

Class<?> java.lang.reflect.Proxy.getProxyClass0(ClassLoader loader, Class<?>... interfaces);
 
由於伺服器上不能斷點分析,以及無法修改jdk新增日誌,透過複製關鍵程式碼到自己程式碼開始丟擲異常處列印日誌,發現:
            Class<?> interfaceClass = null;
            try {
                interfaceClass = Class.forName(interfaceName, false, loader);
            } catch (ClassNotFoundException e) {
            }
            if (interfaceClass != interfaces[i]) {
                throw new IllegalArgumentException(
                    interfaces[i] + " is not visible from class loader");
            }        
interfaceClass 為null值。

然後對比之前的開發程式碼:
之前:
public RPCGameAction gameAction = (RPCGameAction) Container
            .createRemoteService(RPCGameAction.class, "gamecenter");



現在:
public RPCGameAction getGameAction(String prefix)
    {
        
        return (RPCGameAction) Container
                .createRemoteService(RPCGameAction.class, prefix);
    }

而建立代理的程式碼中的獲取類載入器的程式碼為:
ClassLoader loader = Thread.currentThread().getContextClassLoader();

 前者會在初始化的時候已經建立好,而後者會根據執行時的ClassLoader而建立,而openfire載入外掛的類載入器跟執行的不一致,從而導致建立失敗。

解決的方法可以是:RPCGameAction 這個代理隨外掛啟動而建立到記憶體中;

         把介面所處的jar包放到../openfire/lib 目錄下。

 

相關文章