The service loader does not find the class of the service provider, although the class is in the same JAR file as META-INF / services

I successfully run a C ++ application that loads a JVM with a JAR file as a classpath argument. The application then successfully uses JNI calls to perform various functions defined in the .class files in this JAR file.

The .jar file directory structure includes a third-party set of .class files - those that were combined with jai_imageio.jar (these .class files with their full directory structure were combined into this single .jar file using Intellij IDEA). Also included in the combined .jar file are lines from the original jai_imageio.jar manifest.mf - in particular, implementation-title and related lines. In addition, there is a meta-inf/services folder, also copied from jai_imageio.jar. The various services listed in the services directory look correct.

In particular, javax.imageio.spi.ImageOutputStreamSpi in the meta-inf/services folder in the .jar file contains a single line com.sun.media.imageioimpl.stream.ChannelImageOutputStreamSpi , and there is a class corresponding to this in the .jar file, exactly in the directory indicated by this line: com/sun/media/imageioimpl/stream/ChannelImageOutputStreamSpi.class .

However, when the Java code executes the following line:

 ImageIO.write(image, "tiff", file); // Assume 'image' is a BufferedImage and 'file' is a File 

... it throws an exception:

 java.util.ServiceConfigurationError: javax.imageio.spi.ImageOutputStreamSpi: Provider com.sun.media.imageioimpl.stream.ChannelImageOutputStreamSpi not found 

... although this class present in the same .jar file as above.

Can someone explain why this error occurs, and what I have to do to resolve it.

+6
source share
1 answer

From this documentation http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/invocation.html

"When the thread is connected to the virtual machine, the context class loader is the boot loader."

Any native thread connected to the JVM via AttachCurrentThread () receives only the bootstrap class loader, even the system class loader. The classes referenced by ServiceLoader will not be available unless you explicitly install a new thread context class loader.

This can be done like this:

 java.lang.Thread.currentThread().setContextClassLoader( java.lang.ClassLoader.getSystemClassLoader() ); 
+2
source

Source: https://habr.com/ru/post/915275/


All Articles