2012-06-28 7 views
6

Ho un'eccezione, mentre io eseguo questo codice:metodo funziona nella riflessione, ma non in modo "normale" in Java

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

e l'eccezione è:

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) 

Questo l'eccezione viene generata quando il codice viene eseguito su una macchina IBM, quando viene eseguito su una macchina Windows funziona correttamente.

Ricercando questo, ho scoperto che la classe di ritorno per si.getDigestAlgoritmId() è diversa per le macchine IBM. Per IBM java è com.ibm.security.x509.AlgorithmId e per java6 è sun.security.x509.AlgorithmId. E entrambe le classi hanno un metodo getName().

Ma la cosa più strana è che se richiamo il metodo tramite riflessione l'eccezione non viene visualizzata e funziona correttamente in entrambi gli ambienti. Qualcuno può rispondere perché funziona così?

Penso che la soluzione sia farlo con il riflesso, ma mi piacerebbe sapere il motivo per cui con il riflesso funziona e il modo normale non lo fa. Principalmente per evitare errori simili in futuro.

Grazie in anticipo e mi dispiace per il mio pessimo inglese.

Edit: La chiamata riflessione:

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

Sarebbe positivo se si aggiungesse come si chiama il metodo usando la riflessione. –

risposta

2

SignerInfo.getDigestAlgoritmId() ha diverse dichiarazioni in tali due versioni di Java. Se si compila la classe con una dichiarazione, non funzionerà con l'altra. Il tipo è memorizzato nel tuo file .class e deve corrispondere in fase di esecuzione.

Se si utilizza la riflessione, non è necessaria la dichiarazione di getDigestAlgoritmId in fase di compilazione. Funzionerà con qualsiasi dichiarazione, purché corrisponda al nome e ai parametri specificati.

Fare attenzione alla riflessione. sun.security.x509.AlgorithmId non sembra essere parte dell'API java pubblica. Potrebbe differire tra versioni e venditori. Questi due differiscono solo per i tipi di ritorno. Chissà quali differenze ci sono in altre implementazioni Java. Se possibile, attenersi alle API Java ufficiali.