0

我正在实现一个 OSGI 包(使用kura)来做一些 AES 加密。我直接在我的包中添加了第三个库 javax.crypto,这是清单:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: AES
Bundle-SymbolicName: org.eclipse.kura.AES
Bundle-Version: 1.0.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Import-Package: org.osgi.service.component;version="1.2.0",
 org.slf4j;version="1.7.21"
Service-Component: component.xml
Export-Package: org.eclipse.kura.AES.services
Bundle-ClassPath: .,
 lib/javax-crypto.jar

尝试解密时出现此错误:

java.lang.ClassCastException: com.sun.crypto.provider.AESCipher$General cannot be cast to javax.crypto.CipherSpi
        at javax.crypto.Cipher.getInstance(Cipher.java:166)
        at org.eclipse.kura.AES.services.AesServices.decrypt(AesServices.java:33)
        at org.eclipse.kura.AES.AES_Activator.activate(AES_Activator.java:19)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.eclipse.equinox.internal.ds.model.ServiceComponent.activate(ServiceComponent.java:235)
        at org.eclipse.equinox.internal.ds.model.ServiceComponentProp.activate(ServiceComponentProp.java:146)
        at org.eclipse.equinox.internal.ds.model.ServiceComponentProp.build(ServiceComponentProp.java:347)
        at org.eclipse.equinox.internal.ds.InstanceProcess.buildComponent(InstanceProcess.java:620)
        at org.eclipse.equinox.internal.ds.InstanceProcess.buildComponents(InstanceProcess.java:197)
        at org.eclipse.equinox.internal.ds.Resolver.buildNewlySatisfied(Resolver.java:473)
        at org.eclipse.equinox.internal.ds.Resolver.enableComponents(Resolver.java:217)
        at org.eclipse.equinox.internal.ds.SCRManager.performWork(SCRManager.java:816)
        at org.eclipse.equinox.internal.ds.SCRManager$QueuedJob.dispatch(SCRManager.java:783)
        at org.eclipse.equinox.internal.ds.WorkThread.run(WorkThread.java:89)
        at org.eclipse.equinox.internal.util.impl.tpt.threadpool.Executor.run(Executor.java:70)

我在我的树莓派上使用 openjdk。我尝试使用 oracle java,但仍然遇到同样的问题。要么我没有完全删除 openjdk,要么还有其他我无法确定的原因。有任何想法吗?

4

3 回答 3

1

正如其他答案中提到的,您必须非常小心,以避免通过您的 API 暴露内部包。在这种情况下,您提供的清单和堆栈跟踪指向许多严重和致命的问题。

提供的清单定义了以下 Import-Package 语句。

Import-Package: org.osgi.service.component;version="1.2.0",
    org.slf4j;version="1.7.21"

由于以下几个原因,这立即令人怀疑:

  1. 堆栈跟踪证明您想通过 javax.crypto 使用 AES,但不要导入包。相反,您已将 API 重新打包到您的包中,而不是实现。如果要使用 JDK 实现,则需要与其共享一个类空间。

  2. 您导入声明式服务 API (org.osgi.service.component) 这样做是不寻常的,因为 DS 组件通常是 POJO。

  3. 您的导入都使用单个版本,而不是版本范围。在 OSGi 用语中,这意味着您的导入是从版本 X 到无穷大。这是一种反模式。

我从这些问题推测您的清单是手工创建的。我强烈建议您使用工具((例如 bnd)来生成清单,因为它会阻止您犯许多这些错误。

于 2017-04-19T16:32:20.743 回答
1

如果使用不同的包解决同一个类,您得到的错误是典型的。

我怀疑你将包嵌入javax.crypto到你的包中。因此,您的捆绑包看到内部类 CipherSpi,而外部捆绑包看到 jdk 或其他捆绑包的版本。

解决方案是确保您仅从一个来源解析此类 api 包。在您的情况下,导入包javax.crypto而不是嵌入javax-crypto.jar. 相反,您必须从 jdk 导出包或安装包含它的包。

一般规则是永远不要嵌入可能通过您向外界公开的 api 可见的包。

于 2017-04-19T09:45:34.570 回答
1

对于我的情况,添加后问题得到解决,

@PowerMockIgnore({"javax.crypto.*"})在课堂上

在这里你可以找到问题的 git 链接

于 2020-12-15T15:42:10.510 回答