所以我完成了我的应用程序编码以旋转TIFF图像,这需要JAI来操纵TIFF。
在Eclipse下工作时它工作正常,但每当我为库构建一个胖jar然后创建一个实现它(每http://fjep.sourceforge.net/fjeptutorial.html),当我执行java -jar Push.jar \ path \时\ dir,它一直运行直到它到达压缩和保存的部分:
TIFFImageWriterSpi tiffspi = new TIFFImageWriterSpi();
ImageWriter writer = tiffspi.createWriterInstance();
//Iterator<ImageWriter> iter = ImageIO.getImageWritersByFormatName("TIFF");
//ImageWriter writer = iter.next();
ImageWriteParam param2 = writer.getDefaultWriteParam();
param2.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param2.setCompressionType("LZW");
param2.setCompressionQuality(0.0f);
File fOutputFile = workArea[i];
ImageOutputStream ios = ImageIO.createImageOutputStream(fOutputFile);
writer.setOutput(ios);
if (frontPage == 1)
{
writer.write(null, new IIOImage(pg1, null, null), param2);
writer.writeInsert(-1, new IIOImage(pg2, null, null), param2);
}
else if (frontPage == 2)
{
writer.write(null, new IIOImage(pg2, null, null), param2);
writer.writeInsert(-1, new IIOImage(pg1, null, null), param2);
}
remaining = remaining - 1;
if (remaining > 0)
System.out.println(remaining + " remaining.");
else
System.out.println("Done.");
它在该部分的第一行显示消息:
Exception in thread "main" java.lang.IllegalArgumentException: vendorName == null!
....rest of stack trace.
答案 0 :(得分:26)
由于我花了相当多的时间来调试这个问题,我想我会在这里分享我的解决方案,尽管问题的年代。 Srikanth的第二个link特别有用。
JAI需要一些供应商名称用于其深层内部,尤其是javax.imageio.spi.IIOServiceProvider,它被许多(所有?)图像阅读器用于其低级IO。字符串是什么并不挑剔,但它不能为空。
ImageReaderSpi类不是硬编码供应商名称,而是从sun.media.imageioimpl.common.PackageUtil.getVendor()获取供应商名称。这反过来从jar的MANIFEST.MF 中读取它。通常,您会链接到标准的jai-imageio packagage,因此Sun的供应商信息会被读取。但是,由于您正在创建一个胖文件夹,因此您将Sun的MANIFEST.MF替换为您自己的缺少所需信息的文件。
在MANIFEST.MF文件中包含以下行:
Specification-Title: Java Advanced Imaging Image I/O Tools Specification-Version: 1.1 Specification-Vendor: Sun Microsystems, Inc. Implementation-Title: com.sun.media.imageio Implementation-Version: 1.1 Implementation-Vendor: Sun Microsystems, Inc.
每个属性的值可以是任何值(我使用我的特定应用程序/版本/公司),只要定义了所有六个属性。
如果你使用maven的程序集插件来创建你的胖罐,maven可以自动包含正确的版本号等。使用以下pom.xml
部分更新您的<archive>
:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
<manifestEntries>
<Specification-Vendor>MyCompany</Specification-Vendor>
<Implementation-Vendor>MyCompany</Implementation-Vendor>
</manifestEntries>
</archive>
</configuration>
<executions>
<execution>
<id>create-my-bundle</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
答案 1 :(得分:4)
我不得不使用这个ImageIO jar。它就像一个魅力。找到它here。
答案 2 :(得分:3)
Quantum7接受的答案解释了问题的根源,在 Maven 部分,它提供了一个解决方案,当使用Maven Assembly插件生成包含依赖项的JAR时。如果您使用Maven Shade插件来生成具有依赖项的JAR,则配置略有不同。您可以在pom.xml
:
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>com.conveyal.r5.R5Main</Main-Class>
<Specification-Title>Java Advanced Imaging Image I/O Tools</Specification-Title>
<Specification-Version>1.1</Specification-Version>
<Specification-Vendor>Sun Microsystems, Inc.</Specification-Vendor>
<Implementation-Title>com.sun.media.imageio</Implementation-Title>
<Implementation-Version>1.1</Implementation-Version>
<Implementation-Vendor>Sun Microsystems, Inc.</Implementation-Vendor>
<Extension-Name>com.sun.media.imageio</Extension-Name>
</manifestEntries>
</transformer>
</transformers>
</configuration>
答案 3 :(得分:1)
答案 4 :(得分:1)
我遇到的问题略有不同,我在尝试运行已编译的jar文件时遇到“ClassNotFound”错误。我在研究时碰巧遇到了这个问题,所以对于那些跟我走过同样道路的人来说,你走了。
对于稍后可能会发现此问题的人,如果其他任何内容似乎无效,您可以尝试使用Maven的Apache Shader插件。 Here是关于它的更多信息。
我没有足够的经验告诉你如何它,但Apache Shader将项目中所有使用的依赖项打包到最终的jar文件中,因此所有依赖项都是在构建时包含在META-INF文件夹中。这会增加jar文件的大小(取决于您在项目中使用的库数量),但似乎也修复了jar无法从使用的外部库中查找类。
要使用Shader插件,请将以下内容添加到POM中。我将它包含在依赖项标记之后和属性标记之前。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>com.package.name.className</Main-Class>
<Build-Number>1</Build-Number>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
注意 :确保更改包和类名以反映项目的包和类名。
其他有用的链接:Similar stack overflow question
答案 5 :(得分:1)
(如果我有足够的声誉,本来可以评论Quantum7的答案)
我遇到了同样的问题。 Quantum7的答案节省了一天!然而,在放入manifestEntries Specification-Vendor和Implementation-Vendor之后,我的胖jar的执行仍然失败,下面有例外。注意它是
version == null!
不是
vendorName == null!
java.util.ServiceConfigurationError: javax.imageio.spi.ImageReaderSpi: Provider com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReaderSpi could not be instantiated
at java.util.ServiceLoader.fail(Unknown Source)
at java.util.ServiceLoader.access$100(Unknown Source)
at java.util.ServiceLoader$LazyIterator.nextService(Unknown Source)
at java.util.ServiceLoader$LazyIterator.next(Unknown Source)
at java.util.ServiceLoader$1.next(Unknown Source)
at javax.imageio.spi.IIORegistry.registerApplicationClasspathSpis(Unknown Source)
at javax.imageio.spi.IIORegistry.<init>(Unknown Source)
at javax.imageio.spi.IIORegistry.getDefaultInstance(Unknown Source)
at javax.imageio.ImageIO.<clinit>(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.IllegalArgumentException: version == null!
at javax.imageio.spi.IIOServiceProvider.<init>(Unknown Source)
at javax.imageio.spi.ImageReaderWriterSpi.<init>(Unknown Source)
at javax.imageio.spi.ImageReaderSpi.<init>(Unknown Source)
at com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReaderSpi.<init>(CLibJPEGImageReaderSpi.java:80)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
... 14 more
放入下面的manifestEntries修复它。
<manifestEntries>
<Specification-Title>Java Advanced Imaging Image I/O Tools</Specification-Title>
<Specification-Version>1.1</Specification-Version>
<Specification-Vendor>Sun Microsystems, Inc.</Specification-Vendor>
<Implementation-Title>com.sun.media.imageio</Implementation-Title>
<Implementation-Version>1.1</Implementation-Version>
<Implementation-Vendor>Sun Microsystems, Inc.</Implementation-Vendor>
</manifestEntries>
运行胖罐时,我确保下面代码中的三个值都不为空。
import com.sun.media.imageioimpl.common.PackageUtil;
public class ManifestCheck {
public static void main(String[] args) {
System.out.println(PackageUtil.getVendor());
System.out.println(PackageUtil.getVersion());
System.out.println(PackageUtil.getSpecificationTitle());
}
}
答案 6 :(得分:1)
在努力寻找许多解决方案后,我也遇到了同样的错误,找到了这个并为我工作。
需要在代码中手动给出 venderName 为:
import com.sun.media.imageioimpl.common.PackageUtil;
try {
MainClass.afVenderNames(PackageUtil.class, "afreen", "afreen", "afreen");
} catch (NoSuchFieldException e1) {
e1.printStackTrace();
} catch (SecurityException e1) {
e1.printStackTrace();
} catch (IllegalArgumentException e1) {
e1.printStackTrace();
} catch (IllegalAccessException e1) {
e1.printStackTrace();
}
System.out.println(PackageUtil.getVendor());
System.out.println(PackageUtil.getVersion());
System.out.println(PackageUtil.getSpecificationTitle());
public static void afVenderNames(Class<?> PackageUtil, String vendor, String version, String specTitle)
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
Field vendorField = PackageUtil.getDeclaredField("vendor");
vendorField.setAccessible(true);
vendorField.set(null, vendor);
Field versionField = PackageUtil.getDeclaredField("version");
versionField.setAccessible(true);
versionField.set(null, version);
Field specTitleField = PackageUtil.getDeclaredField("specTitle");
specTitleField.setAccessible(true);
specTitleField.set(null, specTitle);
}
如果 vendorName 值不是 NULL,那么它是什么并不重要。 我的代码在 Eclipse 中运行良好,但在导出的可运行 jar 中出现异常。
写完上面的代码并导出jar时终于工作了。