2013-07-01 2 views
2

Для некоторых особых случаев использования у меня есть небольшая утилита для загрузки классов Java из банок с использованием динамического загрузчика классов DynamicClassLoader. Это отлично подходит для классов Java, содержащихся в баночках. Загрузка классов 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

Очевидно, что вы должны сделать общедоступный конструктор по умолчанию (он не будет работать для классов Java без общедоступного конструктора по умолчанию). Например.

class ScalaClassYYY() { 
    ... 
} 

или если вы хотите основной конструктор принимать некоторые аргументы,

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

Но из

Примечания скомпилированного Scala имя класса, заканчивая $

кажется как вы на самом деле пытаетесь создать экземпляр Scala object:

object ScalaClassYYY { ... } 

В этом случае, вы не должны создавать новый экземпляр и вместо этого использовать the existing one:

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

EDIT:

Я не вижу в своем ответе хау вы добавляете публичный конструктор по умолчанию в класс Scala, который НЕ требует каких-либо параметров.

class (неobject), который не требует каких-либо параметров имеет открытый конструктор по умолчанию уже (мой первый пример).

На самом деле в Java все классы по умолчанию предлагают конструктор по умолчанию общественного

No. только те классы, которые не имеют конструкторов, которые принимают аргументы.

удалить "(он не будет работать для классов 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. Пожалуйста, внимательно прочитайте мой ОП, я сказал, что ** работает ** с Java. Вы правы в том, что являетесь объектом Scala, но мне нужно, чтобы он работал в классе Scala, и это не так. –

+1

Причина, по которой, как мне кажется, связана с частным конструктором, заключается именно в том, что вы пытаетесь создать экземпляр класса объекта Scala '. То, что вы пытаетесь, будет отлично работать для обычных классов Scala (у которых есть общедоступные конструкторы, которые по умолчанию). Но Scala должен контролировать процесс создания объектов для поддержания их одноэлементности. –

+0

@Alexey. Если вы исправите свой ответ, удалите «(он не будет работать для классов Java без конструктора с открытым по умолчанию либо)», потому что это неправильно, я буду принимать ваш ответ –

Смежные вопросы