6

执行此代码时出现异常:

p7 = new PKCS7(p7byte);
...
SignerInfo si = p7.getSignerInfos()[0];
String name = si.getDigestAlgorithmId().getName();

例外是:

Exception in thread "main" java.lang.NoSuchMethodError: sun/security/pkcs/SignerInfo.getDigestAlgorithmId()Lsun/security/x509/AlgorithmId;
        at reflex.Reflex.testPKCS7(Reflex.java:151)
        at reflex.Reflex.main(Reflex.java:43)

当代码在 IBM 机器上执行时会引发此异常,当它在 Windows 机器上执行时它可以正常工作。

对此进行研究,我发现si.getDigestAlgoritmId()IBM 机器的返回类不同。对于 IBM 的 java 是com.ibm.security.x509.AlgorithmId,对于 java6 是sun.security.x509.AlgorithmId. 这两个类都有一个getName()方法。

但最奇怪的是,如果我通过反射调用该方法,则不会出现异常,并且它在两种环境中都能正常工作。有人可以回答为什么它会这样工作吗?

我认为解决方案是用反射来做,但我想知道反射它起作用的原因以及它不起作用的正常方式。主要是为了避免以后再犯类似的错误。

在此先感谢并为我的英语不好感到抱歉。

编辑:反射调用:

try{
  Class clase = si.getClass();
  Method metodo = clase.getMethod("getDigestAlgorithmId");
  Object result = metodo.invoke(si,null); 
  System.out.println("Result.class=" + result.getClass().getName());
  System.out.println("Result=" + result);
}catch(Exception e){...}
4

1 回答 1

2

SignerInfo.getDigestAlgoritmId() has different declarations in those two Java versions. If you compile your class with one declaration, it wont work with the other. The type is stored in your .class file and has to match at run-time.

If you use reflection, you don't need the declaration of getDigestAlgoritmId at compile time. It will work with any declaration, as long as it matches the name and parameters you specified.

Be careful with reflection. sun.security.x509.AlgorithmId doesn't seem to be part of public java API. It might differ between versions and vendors. Those two differ only in return types. Who knows what differences are there in other Java implementations. If possible, stick to official Java API.

于 2012-06-28T15:29:05.653 回答