2014-05-18 51 views
0

我目前遇到了我正在处理的一个小项目的问题。在这个项目中,我试图从配置字符串动态创建类并将其加载到JVM中。在OSGI环境中定义类时ClassFormatError

当我在“正常”环境(单元测试)中执行此操作时,一切正常。但是当我尝试在OSGI环境(Apache Karaf)中创建类时,我收到一个ClassFormatError,其中包含消息“Illegal class name”Ljava/lang/String;“in class ...”。

经过简短的研究,我发现这个问题发生在java/lang中的类中,当它们没有被系统类加载器加载时,但是当涉及到java中的类加载时, OSGi的。

我想我能够访问这些defineClass方法可能是对这一问题感兴趣的方式,使这里是:

 PROTECTION_DOMAIN = (ProtectionDomain) AccessController.doPrivileged(new PrivilegedAction() { 
     public Object run() { 
      return RestEndpoint.class.getProtectionDomain(); 
     } 
    }); 

    AccessController.doPrivileged(new PrivilegedAction() { 
     public Object run() { 
      try { 
       Class loader = Class.forName("java.lang.ClassLoader"); 
       DEFINE_CLASS = loader.getDeclaredMethod("defineClass", 
         new Class[]{ String.class, 
           byte[].class, 
           Integer.TYPE, 
           Integer.TYPE, 
           ProtectionDomain.class }); 
       DEFINE_CLASS.setAccessible(true); 
      } catch (ClassNotFoundException e) { 
       throw new RuntimeException(e); 
      } catch (NoSuchMethodException e) { 
       throw new RuntimeException(e); 
      } 
      return null; 
     } 
    }); 

最后(希望有用)资料片是我的类加载器在OSGi包中运行项目时调用defineClass方法:它是org.apache.felix.framework.BundleWiringImpl的一个实例。

如果有人能帮助我在这里,这将是伟大的!

问候, 帕斯卡尔

编辑: 我需要在运行时定义类,因为我想避免的样板代码在我的项目,使程序更加一致。

更确切地说,我的项目将是一个RESTful WebService。由于我使用多种技术来存储数据和同步进程(mongoDB,MySQL,activeMQ,...),我想使用Apache骆驼来处理所有不同的技术。 问题是,我不知道在REST上很好地将Camel与Java方法集成在一起(整个方法和类到HTTP请求的映射是使用注释完成的)。 所以对我来说唯一的可能是编写方法,将请求的参数放在骆驼的交换头文件中并将它们发送到路由。 为了避免这种情况,我希望通过在路由定义中定义运行时的这些类来自动执行此过程。

+0

你为什么试图定义类java.lang.String?当然,这已经存在,并由启动类加载器定义?在Java中,只有引导类加载器才被允许定义名称以'java.'开头的类。 –

+0

你能否解释一下为什么你要做自定义类的创建?也许还有更好的方法来实现你想要的OSGi。 –

+0

@NeilBartlett我不想定义java.lang.String。我想定义一个全新的课程,例如一个String类型的输入参数。克里斯蒂安,我更新了这个问题,这样你就可以更准确地了解问题。 – user2764975

回答

0

编写自己的父类为bundle's class loader的类加载器,而不是试图破解现有的类加载器。

+0

终于得到它的工作。我不认为破解现有的类加载器是个问题,因为即使在创建我的自定义类加载器之后,我也遇到了同样的问题,因为我创建的字节代码有一点点错误,并且javax.ws.rs注释类不在bundle classpath(BND没有将它们添加到清单中)。但是使用自定义类加载器的方法,它更清洁,所以谢谢你:)。 – user2764975