2013-07-01 116 views
2

對於某些特殊用例,我有一個小型實用程序來使用動態類加載器DynamicClassLoader從jar中加載Java類。這適用於包含在jar中的Java類。從jar加載Scala類也可以毫無問題地工作。但是,實例化加載的Scala類會導致以下異常。它看起來像Scala類有私人默認構造函數?注意編譯Scala的類名$使用反射實例化Scala類Java的`newInstance`

java.lang.IllegalAccessException: Class XXX can not access a member of class ScalaClassYYY$ with modifiers "private" 

下面的代碼片段說明了什麼,我想實現的想法,並給出了一個有點背景下結束。異常發生在註釋行:

// deploy and register the new code 
byte[] jarBytes = (byte[]) ((Object) message.getAttachment("jar")); 
String registerClassName = message.getAttachment("register"); 
logger.debug("the register is '" + registerClassName + "'"); 

DynamicClassLoader loader = new DynamicClassLoader(jarBytes); 
Class<?> registerClass = loader.lookUp(registerClassName); 
// ===> this is where the java.lang.IllegalAccessException happens 
IRegisterExecutor registerExecutor = (IRegisterExecutor) registerClass.newInstance(); 
registerExecutor.register(); 

任何想法如何解決?

回答

5

很明顯,您需要將默認構造函數設爲public(對於沒有公共默認構造函數的Java類也不適用)。例如。

class ScalaClassYYY() { 
    ... 
} 

,或者如果你想主構造帶一些參數,

class ScalaClassYYY(arg1: Int) { 
    def this() = this(0) 
} 

但從

注意編譯Scala的類名$

結束似乎就像你實際上試圖實例化一個Scala 012一樣:

object ScalaClassYYY { ... } 

在這種情況下,你不應該創建一個新的實例,而使用the existing one

(IRegisterExecutor) registerClass.getField("MODULE$").get(null); 

編輯:

我不會在你的答案怎麼看您將默認的公共構造函數添加到不需要任何參數的Scala類。

一個classobject)不需要任何參數早已默認的公共構造(我的第一個例子)。

實際上,在Java中所有類都默認提供了一個公共的默認構造函數沒有構造函數接受參數

號只有那些類。

刪除 「(它沒有公共默認構造函數的Java類的工作,要麼)」,因爲它是錯誤的

documentation for Class.newInstance()

IllegalAccessException - 如果該類或者它的空構造函數不可訪問。

所以我很確定它是正確的。如果它適用於沒有公共默認構造函數的Java類,那麼這似乎是您使用的類加載器中的一個主要錯誤。您可以使用如下所示的Java類對其進行測試:

public class TestClass implements IRegisterExecutor { 
    public TestClass(int dummy) {} 

    // some implementation for IRegisterExecutor methods to get it to compile 
} 
+0

謝謝您的回答。我沒有在你的回答中看到如何將默認公共構造函數添加到不需要任何參數的Scala類。 Java版本沒有問題。實際上,在Java中,所有類默認都提供一個公共的默認構造函數,Scala中似乎不是這種情況。請仔細閱讀我的OP,我說它**與Java一起工作。你對做一個Scala「對象」是正確的,但我需要它爲Scala類工作,而不是。 –

+1

我相信你遇到私有構造函數的原因正是因爲你試圖實例化一個Scala對象的類。你試圖對普通的Scala類(具有公共構造函數,這是默認的)將工作得很好。但是Scala需要控制實例化對象的過程以保持其單例本質。 –

+0

@Alexey如果您更正了答案,請刪除「(它不適用於沒有公共默認構造函數的Java類)」,因爲它是錯誤的,我會接受您的回答 –