对于某些特殊用例,我有一个小的实用程序,可以使用动态类加载器DynamicClassLoader从jar中加载Java类。这对于jars中包含的Java类很好用。从jar加载Scala类也可以正常工作。但是,实例化已加载的Scala类会导致以下异常。看起来Scala类具有私有的默认构造函数?请注意,已编译的Scala类名称以$结尾

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();


任何想法如何解决?

最佳答案

显然,您需要将默认构造函数设为公共(没有公共默认构造函数的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);


编辑:


  我没有在您的答案中看到如何将默认的公共构造函数添加到不需要任何参数的Scala类中。


不需要任何参数的class(不是object)已经具有默认的公共构造函数(我的第一个示例)。


  实际上,在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
}

关于java - 使用反射Java的`newInstance`实例化一个Scala类,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17401565/

10-10 04:11