我正在成功运行一个C ++应用程序,该应用程序使用JAR文件作为类路径参数加载JVM。然后,应用程序成功使用JNI调用来执行此JAR文件中.class文件中定义的各种函数。
.jar文件的目录结构中包含第三方.class文件集 - 这些文件是从jai_imageio.jar合并的(这些.class文件及其完整目录结构使用Intellij合并到此单个.jar文件中理念)。合并后的.jar文件中还包含原始jai_imageio.jar manifest.mf
中的行 - 特别是implementation-title
和相关行。此外,还存在meta-inf/services
文件夹,也是从jai_imageio.jar复制的。 services
目录中列出的各种服务看起来是正确的。
特别是.jar文件中javax.imageio.spi.ImageOutputStreamSpi
文件夹中的meta-inf/services
包含单行com.sun.media.imageioimpl.stream.ChannelImageOutputStreamSpi
,并且.jar文件中有一个与此对应的类恰好是该行指示的目录:com/sun/media/imageioimpl/stream/ChannelImageOutputStreamSpi.class
。
但是,当Java代码执行以下行时:
ImageIO.write(image, "tiff", file); // Assume 'image' is a BufferedImage and 'file' is a File
...它抛出异常:
java.util.ServiceConfigurationError: javax.imageio.spi.ImageOutputStreamSpi:
Provider com.sun.media.imageioimpl.stream.ChannelImageOutputStreamSpi not found
...即使此类 出现在同一个.jar文件中,如上所述。
有人可以解释为什么会发生这种错误,以及我应该怎么做才能解决它。
答案 0 :(得分:2)
从此文档中 http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/invocation.html
“当线程附加到VM时,上下文类加载器是引导加载程序。”
通过AttachCurrentThread()连接到JVM的任何本机线程只获取引导类加载器,甚至不获取系统类加载器。除非您明确修复新线程的上下文类加载器,否则ServiceLoader引用的类将不可用。
这可以这样做:
java.lang.Thread.currentThread().setContextClassLoader(
java.lang.ClassLoader.getSystemClassLoader()
);