2012-06-28 3 views
6

ich eine Ausnahme habe, während ich diesen Code ausführen:Methode funktioniert in der Reflexion, aber nicht in "normalen Weg" in Java

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

Und die Ausnahme ist:

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) 

Diese Ausnahme wird ausgelöst, wenn der Code auf einem IBM-Computer ausgeführt wird. Wenn er auf einem Windows-Computer ausgeführt wird, funktioniert er ordnungsgemäß.

Nachforschend, habe ich herausgefunden, dass die Rückgabeklasse für si.getDigestAlgoritmId() für IBM Maschinen unterschiedlich ist. Für IBMs Java ist es com.ibm.security.x509.AlgorithmId und für Java6 ist es sun.security.x509.AlgorithmId. Und beide Klassen haben eine getName() Methode.

Aber das Seltsamste ist, dass, wenn ich die Methode durch Reflexion aufrufen die Ausnahme nicht erscheint, und es funktioniert in beiden Umgebungen korrekt. Kann jemand antworten, warum es so funktioniert?

Ich denke, dass die Lösung ist, es mit der Reflexion zu tun, aber ich möchte den Grund wissen, warum mit der Reflexion es funktioniert und die normale Art und Weise es nicht tut. Hauptsächlich um ähnliche Fehler in der Zukunft zu vermeiden.

Vielen Dank im Voraus und Entschuldigung für mein schlechtes Englisch.

Edit: Der Reflexions Aufruf:

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){...} 
+1

Es wäre gut, wenn Sie hinzufügen, wie Sie die Methode mit Reflektion aufrufen. –

Antwort

2

SignerInfo.getDigestAlgoritmId() hat verschiedene Erklärungen in diesen beiden Java-Versionen. Wenn Sie Ihre Klasse mit einer Deklaration kompilieren, funktioniert sie nicht mit der anderen. Der Typ wird in der Datei .class gespeichert und muss zur Laufzeit übereinstimmen.

Wenn Sie Reflexion verwenden, benötigen Sie zur Kompilierungszeit nicht die Deklaration getDigestAlgoritmId. Es funktioniert mit jeder Deklaration, solange es mit dem Namen und den Parametern übereinstimmt, die Sie angegeben haben.

Seien Sie vorsichtig mit der Reflexion. sun.security.x509.AlgorithmId scheint nicht Teil der öffentlichen Java API zu sein. Es kann sich zwischen Versionen und Anbietern unterscheiden. Diese beiden unterscheiden sich nur in Rückgabetypen. Wer weiß, welche Unterschiede es in anderen Java-Implementierungen gibt. Wenn möglich, bleiben Sie bei der offiziellen Java API.

Verwandte Themen