方法在反射中工作,但在 Java 中"normal way"不起作用



我在执行此代码时遇到异常:

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 机器上执行时,它会正常工作。

通过研究这个问题,我发现 IBM 机器的 si.getDigestAlgoritmId() 返回类是不同的。对于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){...}
SignerInfo.getDigestAlgoritmId()

这两个Java版本中有不同的声明。如果使用一个声明编译类,则它将无法与另一个声明一起使用。类型存储在.class文件中,必须在运行时匹配。

如果使用反射,则不需要在编译时声明getDigestAlgoritmId。它将适用于任何声明,只要它与您指定的名称和参数匹配即可。

小心反思。 sun.security.x509.AlgorithmId似乎不是公共Java API的一部分。它可能因版本和供应商而异。这两者仅在返回类型上有所不同。谁知道其他Java实现有什么区别。如果可能的话,坚持使用官方的Java API。

最新更新