Java 为什么NPE使用DatatypeConverter的静态方法?

Java 为什么NPE使用DatatypeConverter的静态方法?,java,string,nullpointerexception,base64,type-conversion,Java,String,Nullpointerexception,Base64,Type Conversion,我盯着这段短代码看得太久了,我一辈子都看不出它怎么会在第6行抛出NullPointerException。为什么是NPE class ConvertTest { public static void main(String[] args) throws Exception { byte[] b = "Ha".getBytes("UTF-8"); System.out.println("bytes: " + b.length); javax

我盯着这段短代码看得太久了,我一辈子都看不出它怎么会在第6行抛出
NullPointerException
。为什么是NPE

class ConvertTest {

    public static void main(String[] args) throws Exception {
        byte[] b = "Ha".getBytes("UTF-8");
        System.out.println("bytes: " + b.length);
        javax.xml.bind.DatatypeConverter.printBase64Binary(b);  // NPE!
    }
}
输出 更新 虽然许多错误报告都指向1.7版本,但我惊讶地看到Eclipse被配置为使用
1.6.0\u 32
&TextPad发现了
1.6.0-b105
(甚至没有意识到安装了该版本!)

两个JRE都会因该NPE而失败

public static String printBase64Binary( byte[] val ) {
    return theConverter.printBase64Binary( val );
}
JAXB提供程序需要在以下位置调用setDatatypeConverter api: 第一次封送或解封送操作之前的某个点(可能是 在调用JAXBContext.newInstance时)。这一步是必要的 配置用于执行打印和打印的转换器 解析功能

首先尝试设置转换器

/**
     * This method is for JAXB provider use only.
     * <p>
     * JAXB Providers are required to call this method at some point before
     * allowing any of the JAXB client marshal or unmarshal operations to
     * occur.  This is necessary to configure the datatype converter that 
     * should be used to perform the print and parse conversions.
     * 
     * <p>
     * Calling this api repeatedly will have no effect - the 
     * DatatypeConverterInterface instance passed into the first invocation is 
     * the one that will be used from then on.
     * 
     * @param converter an instance of a class that implements the 
     * DatatypeConverterInterface class - this parameter must not be null.
     * @throws IllegalArgumentException if the parameter is null
     */
    public static void setDatatypeConverter( DatatypeConverterInterface converter ) {
        if( converter == null ) {
            throw new IllegalArgumentException( 
                Messages.format( Messages.CONVERTER_MUST_NOT_BE_NULL ) );
        } else if( theConverter == null ) {
            theConverter = converter;
        }
    }
/**
*此方法仅供JAXB提供程序使用。
*
*JAXB提供程序需要在之前的某个时间调用此方法
*允许执行任何JAXB客户端封送或解组操作
*发生。这是配置所需的数据类型转换器所必需的
*应用于执行打印和分析转换。
* 
*
*重复调用此api将无效-
*传递到第一个调用的DatatypeConverterInterface实例为
*从那时起将使用的一个。
* 
*@param converter实现
*DatatypeConverterInterface类-此参数不能为null。
*如果参数为null,则@引发IllegalArgumentException
*/
公共静态无效setDatatypeConverter(DatatypeConverterInterface converter){
if(converter==null){
抛出新的IllegalArgumentException(
Messages.format(Messages.CONVERTER_必须不为空);
}else if(converter==null){
转换器=转换器;
}
}

现在JDK7中的JAXB中似乎存在bug,驼峰上的这个问题就证明了这一点:

它最终链接到java.net上的JAXB项目中的这个问题


我不完全确定你是否遇到了同样的事情,但是,也许可以尝试将JDK6与最新的JAXB版本一起使用,看看是否会发生相同的NPE。

如果没有环境的细节,我无法确定是否会发生这种情况,但如果您使用的是JAXB RI,则可能会遇到此JAXB错误所描述的问题:

虽然该bug没有专门解决您遇到的问题(它与
parseDate
方法有关),但根本原因可能是相同的。它是在JAXB的2.2.1版本中检测到的,但在2.1.x版本中可能已经存在,JAXB 2.1.1似乎是集成到1.6中的最新版本(集成在1.6u14中)

该问题表示,它是通过JAXB2.2.4解决的,JAXB2.2.4集成到1.7中


附加说明-当尝试使用1.6u31时,记录了一个有关
parseBoolean
的NPE的相关问题,这可能会引起兴趣(尽管帮助不大,但描述非常简短):。这表明这可能仍然是一个持续的问题,这取决于您是使用RI还是其他JAXB实现。

Whoa!安德鲁·汤普森在问一个问题:我没有得到任何NPE。输出字节:2。在Netbeans中运行了完全相同的代码。@Eng.Fouad你不认为我建立了50K代表。你认为我是白费力气吗?我用它来奖励我的问题这可能与jdk源代码有关吗?在jdk源代码中,DatatypeConverter使用内部impl。impl为空是唯一可能导致NPE的因素。这似乎与@RoddyOfFrozenpeas的建议一致,即问题与混乱/冲突的jaxb库有关。您不应该自己打这个电话。jaxb提供程序应该这样做,但此时可能没有正确初始化/配置jaxb提供程序。
/**
     * This method is for JAXB provider use only.
     * <p>
     * JAXB Providers are required to call this method at some point before
     * allowing any of the JAXB client marshal or unmarshal operations to
     * occur.  This is necessary to configure the datatype converter that 
     * should be used to perform the print and parse conversions.
     * 
     * <p>
     * Calling this api repeatedly will have no effect - the 
     * DatatypeConverterInterface instance passed into the first invocation is 
     * the one that will be used from then on.
     * 
     * @param converter an instance of a class that implements the 
     * DatatypeConverterInterface class - this parameter must not be null.
     * @throws IllegalArgumentException if the parameter is null
     */
    public static void setDatatypeConverter( DatatypeConverterInterface converter ) {
        if( converter == null ) {
            throw new IllegalArgumentException( 
                Messages.format( Messages.CONVERTER_MUST_NOT_BE_NULL ) );
        } else if( theConverter == null ) {
            theConverter = converter;
        }
    }