JAI vendorname == null

时间:2011-08-13 16:02:10

标签: java jai

所以我完成了我的应用程序编码以旋转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.

7 个答案:

答案 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的程序集插件来创建你的胖罐,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

的Shade插件的配置部分添加以下内容
<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)

这些可以帮助您解决问题。

How to run jai-imageio with source code

vendorName == null

答案 4 :(得分:1)

声明

我遇到的问题略有不同,我在尝试运行已编译的jar文件时遇到“ClassNotFound”错误。我在研究时碰巧遇到了这个问题,所以对于那些跟我走过同样道路的人来说,你走了。

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时终于工作了。