【问题标题】:ClassFormatError when defining class in OSGI environment在 OSGI 环境中定义类时出现 ClassFormatError
【发布时间】:2014-07-06 19:39:26
【问题描述】:

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

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

经过简短的研究后,我发现 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 方法的 ClassLoader:它是 org.apache.felix.framework.BundleWiringImpl 的一个实例。

如果有人可以在这里帮助我,那就太好了!

您好, 帕斯卡

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

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

【问题讨论】:

  • 你为什么要定义类java.lang.String?肯定已经存在并且由引导类加载器定义?在 Java 中,仅允许引导类加载器定义名称以 java. 开头的类。
  • 你能解释一下你为什么要创建自定义类吗?也许还有更好的方法可以在 OSGi 中实现您想要的。
  • @NeilBartlett 我不想定义 java.lang.String。我想定义一个全新的类,例如String 类型的输入参数。克里斯蒂安,我更新了问题,以便您可以更准确地了解问题。

标签: java osgi classloader karaf


【解决方案1】:

编写您自己的类加载器,其父类是bundle's class loader,而不是试图侵入现有的类加载器。

【讨论】:

  • 终于让它工作了。我不认为破解现有的类加载器是问题,因为即使在创建我的自定义类加载器之后我也遇到了同样的问题,因为我创建的字节码中有一个小错误并且 javax.ws.rs 注释类不在捆绑类路径(BND 没有将它们添加到清单中)。但是使用自定义的 classLoader 方法会更干净,所以谢谢你:)。
猜你喜欢
  • 1970-01-01
  • 2013-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多