【问题标题】:OSGI - How to solve: ClassNotFoundException? (org.eclipse.osgi.internal.loader.BundleLoader.findClass)OSGI - 如何解决:ClassNotFoundException? (org.eclipse.osgi.internal.loader.BundleLoader.findClass)
【发布时间】:2021-09-01 06:04:00
【问题描述】:

当使用三个包时 A = first.bundle B = second.bundle 和 C = third.bundle,其中 A 依赖于 B和C,C调用方法java.lang.Class.forName

时找不到B的类

是否在任何 pom.xml 文件中缺少配置或以任何其他方式为 bunlde C 的 ClassLoader 配备 B.SecondClass 类?

org.example.first.bundle.FirstClass

public void topLevelMethod() {
  ThirdClass thirdObject = new ThirdClass();
  thirdObject.resolveTheClassName("org.example.second.bundle.SecondClass")
}

org.example.third.bundle.ThirdClass

public <T> Class<T> resolveTheClassName(String className) throws ClassNotFoundException {
  return (Class<T>) Class.forName(className);
}

java.lang.ClassNotFoundException:在 org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:516) 上的 third.bundle_1.0.0.SNAPSHOT 找不到 org.example.second.bundle.SecondClass 在 org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:171) 在 java.lang.ClassLoader.loadClass(ClassLoader.java:357) 在 java.lang.Class.forName0(本机方法) 在 java.lang.Class.forName(Class.java:264) 在 org.example.third.bundle.ThirdClassA.getContentType(ThirdClassA.java:100) 在 org.example.third.bundle.ThirdClassB$ReceivingTask.run(ThirdClassB.java:135) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) 在 java.lang.Thread.run(Thread.java:748)

first.bundle/pom.xml

<dependencies>
    <groupId>${project.groupId}</groupId>
    <artifactId>second.package</artifactId>
    <version>1.0-SNAPSHOT</version>
    <scope>provided</scope>
    <groupId>${project.groupId}</groupId>
    <artifactId>third.package</artifactId>
    <version>1.0-SNAPSHOT</version>
    <scope>provided</scope>
</dependencies>

second.bundle/pom.xml

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
            <extensions>true</extensions>
            <configuration>
                <instructions>
                    <Bundle-SymbolicName>${project.name}</Bundle-SymbolicName>
                    <Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
                    <Embed-Directory>OSGI-INF/lib</Embed-Directory>
                    <Embed-Transitive>true</Embed-Transitive>
                    <Import-Package>
                        *;resolution:=optional
                    </Import-Package>
                    <Export-Package>
                        org.example.second.bundle
                    </Export-Packlage>
                </instructions>
            </configuration>
        </plugin>
    </plugins>
</build>

third.bundle/pom.xml

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
            <extensions>true</extensions>
            <configuration>
                <instructions>
                    <Bundle-SymbolicName>${project.name}</Bundle-SymbolicName>
                    <Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
                    <Embed-Directory>OSGI-INF/lib</Embed-Directory>
                    <Embed-Transitive>true</Embed-Transitive>
                    <Import-Package>
                        *;resolution:=optional
                    </Import-Package>
                    <Export-Package>
                        org.example.third.bundle
                    </Export-Packlage>
                </instructions>
            </configuration>
        </plugin>
    </plugins>
</build>

【问题讨论】:

    标签: java maven osgi bundle classnotfoundexception


    【解决方案1】:

    类加载器配置在一个图中,每个导入的包都有边。因此,如果 C 没有 B 中的包的导入边缘,则 C 无法从 B 中的该包中类加载类。

    如果 C 有来自 B 的对象,它可以在 Class.forName 调用中使用来自 B 的对象的类的类加载器。但通常不应该在 OSGi 中使用 Class.forName。使用 OSGi 服务会更好。然后 C 可以在 OSGi 服务注册表中找到感兴趣的对象。

    【讨论】:

    • 谢谢,我研究了原生 OSGI 方法并找到了解决方案
    【解决方案2】:

    找到了解决办法!

    public <T> Class<T> resolveTheClassName(String className) throws ClassNotFoundException {
      BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
            List<Class<?>> foundClasses = findClass(bundleContext, serializedContentType);
            if(foundClasses.isEmpty()) {
                return (Class<T>)Class.forName(serializedContentType);
            } else {
                return (Class<T>)foundClasses.get(0);
            }
    }
    
    private List<Class<?>> findClass(BundleContext context, String name) {
        List<Class<?>> result = new ArrayList<Class<?>>();
        for (Bundle b : context.getBundles()) {
            try {
                Class<?> c = b.loadClass(name);
                result.add(c);
            } catch (ClassNotFoundException e) {
                // No problem, this bundle doesn't have the class
            }
        }
        return result;
    }
    

    How to load a class by classname string from OSGi runtime environment?

    【讨论】:

      猜你喜欢
      • 2013-06-28
      相关资源
      最近更新 更多