2012-05-09 6 views
6

Sto eseguendo con successo un'applicazione C++ che carica una JVM con un file JAR come argomento del percorso di classe. L'applicazione utilizza quindi con successo chiamate JNI per eseguire varie funzioni definite in file .class all'interno di questo file JAR.Il caricatore di servizi non individua la classe del service provider, anche se la classe è nello stesso file JAR di META-INF/services

Incluso nella struttura di directory del file .jar è un insieme di file .class di terze parti - quelli uniti da jai_imageio.jar (questi file .class, con la loro struttura di directory completa, sono stati uniti in questo singolo file .jar usando Intellij IDEA). Nel file .jar unito sono incluse anche le linee del manifest.mf originale di jai_imageio.jar, in particolare implementation-title e le righe correlate. Inoltre, è presente la cartella meta-inf/services, anch'essa copiata da jai_imageio.jar. I vari servizi elencati all'interno della directory services sembrano corretti.

In particolare, javax.imageio.spi.ImageOutputStreamSpi all'interno della cartella meta-inf/services nel file .jar contiene la singola linea com.sun.media.imageioimpl.stream.ChannelImageOutputStreamSpi, e non v'è una classe corrispondente a questo all'interno del file .jar esattamente la directory indicatted da quella linea: com/sun/media/imageioimpl/stream/ChannelImageOutputStreamSpi.class.

Tuttavia, quando il codice Java esegue la seguente riga:

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

... viene generata un'eccezione:

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

... anche se questa classe è presente all'interno del stesso file .jar, come indicato sopra.

Qualcuno può spiegare perché questo errore sta accadendo e cosa dovrei fare per risolverlo.

+0

Fa lo stesso errore accadere senza JNI coinvolto (cioè solo la chiamata al metodo normalmente da codice Java)? – artbristol

+0

Lo verificherò se necessario, ma sarà una seccatura perché molte chiamate JNI precedenti (eseguite correttamente) eseguono l'installazione. Questi non stanno causando problemi nel senso che i tipi di immagine standard 'jpg',' bmp' e 'png' sono scritti con successo nel file system (assumendo che i file' jai_imageio' .class non siano uniti). Se necessario, lo installerò e lo testerò come suggerisci, anche se speravo di risolverlo senza farlo. –

+1

Non dovrebbe essere necessario eseguire alcuna configurazione - puoi semplicemente creare una classe autonoma con 'ImageIO.write (image," tiff ", file);' in essa, e prova ad eseguire quella classe, con il tuo jar in il classpath. – artbristol

risposta

2

Da questa documentazione http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/invocation.html

"Quando un filo è collegato al VM, il caricatore di classe contesto è il caricatore bootstrap".

Qualsiasi thread nativo collegato a JVM tramite AttachCurrentThread() ottiene solo il caricatore di classe bootstrap, nemmeno il caricatore di classi di sistema. Le classi a cui fa riferimento ServiceLoader non saranno disponibili a meno che non si aggiusti esplicitamente il caricatore della classe di contesto del nuovo thread.

questo può essere fatto come:

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

Stranamente, questo dettaglio pertinente è stato omesso dalla versione corrente della documentazione JNI. – Wheezil

Problemi correlati