Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Method works in reflection but doesn't in "normal way" in Java

I've got an exception while I execute this code:

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

And the exception is:

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)

This exception is thrown when the code is executed on an IBM machine, when it is executed on a Windows machine it works correctly.

Researching this, I have found out that the return class for si.getDigestAlgoritmId() is different for IBM machines. For IBM's java it is com.ibm.security.x509.AlgorithmId and for java6 it is sun.security.x509.AlgorithmId. And both classes have a getName() method.

But the strangest thing is that if I call the method by reflection the exception doesn't appear, and it works correctly in both environments. Can somebody answer why it works this way?

I think that the solution is to do it with reflection, but I would like to know the reason why with reflection it works and the normal way it doesn't. Mainly to avoid similar mistakes in the future.

Thanks in advance and sorry for my bad English.

Edit: The reflection call:

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){...}
like image 484
marsim86 Avatar asked Jun 28 '12 14:06

marsim86


1 Answers

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.

like image 177
Piotr Praszmo Avatar answered Sep 17 '22 14:09

Piotr Praszmo