2010-03-15 7 views
8

zu verpacken Ich möchte ein Stück Code, der absolut muss auf Java 1.5 ausführen. Es gibt einen Teil des Codes, in dem das Programm "erweitert" werden kann, wenn die VM eine 1.6 VM ist.Java: einfachste Möglichkeit, Java 1.5 und 1.6 Code

Im Grunde ist es diese Methode:

private long[] findDeadlockedThreads() { 
    // JDK 1.5 only supports the findMonitorDeadlockedThreads() 
    // method, so you need to comment out the following three lines 
    if (mbean.isSynchronizerUsageSupported()) 
     return mbean.findDeadlockedThreads(); 
    else 
     return mbean.findMonitorDeadlockedThreads(); 
    } 

Was einfachste Weg wäre, diese kompilieren auf 1,5 haben und noch tun das 1,6-Methode aufruft, wenn sie auf 1,6?

In der Vergangenheit habe ich etwas ähnliches getan, indem ich eine einzigartige 1.6-Klasse kompiliert habe, die ich mit meiner App verpacke und mit einem ClassLoader in 1.6 instanziiere (weil eine 1.6 JVM perfekt ist 0x32 und 0x31 Klassen zu mischen), aber Ich denke, es ist ein wenig übertrieben (und ein bisschen peinlich, weil Sie während des Build-Prozesses sowohl 0x31 als auch 0x32 .class-Dateien erstellen müssen).

Wie soll ich gehen, wenn ich die obige Methode auf 1.5 kompilieren wollte? Vielleicht Reflexion verwenden, aber dann, wie (ich bin nicht vertraut mit Reflexion)

Hinweis: Wenn Sie neugierig sind, kommt das obige Verfahren aus diesem Artikel: http://www.javaspecialists.eu/archive/Issue130.html

(aber ich will nicht "Kommentieren Sie die drei Zeilen" wie in dem Artikel, ich möchte, dass dies zu kompilieren und auf beiden 1.5 und 1.6 laufen)

Antwort

3

Sie können dies nicht auf 1.5 kompilieren, aber Sie können auf 1.6 mit der Ziel-Option auf 1.5 (das würde Byte-Code für 1.5 erzeugen) und im Code, der Reflexion verwendet, um herauszufinden, ob die Methode verfügbar ist.

Dieser Code würde die Methode suchen: mbean.getClass(). GetMethod ("findDeadlockedThreads", neue Klasse [0]); Problem ist, es löst eine NoSuchMethodException aus, wenn die Methode nicht vorhanden ist, anstatt einfach null oder etwas Ähnliches zurückzugeben. Das heißt, Sie brauchen Code wie folgt:

Das ist nicht sehr nett, weil es eine Ausnahme verwendet, um eine Entscheidung zu treffen. Das ist wahrscheinlich nicht sehr schnell. Eine Alternative besteht darin, stattdessen getMethods zu verwenden und die zurückgegebene Liste zu durchlaufen, wenn Ihre Methode verfügbar ist. Das ist auch nicht sehr schnell.

EDIT: Christopher Oezbek schlägt in den Kommentaren vor, die Prüfung auf das Vorhandensein der Methode nur einmal zu machen und das Ergebnis zu speichern, um den Overhead für den Try-Catch-Block zu vermeiden. Das ist richtig und eine gute Lösung. matt b warnt, dass die target-Option des Java-Compilers nicht prüft, ob die verwendeten Klassen und Methoden unter Java 1.5 verfügbar sind. Das ist richtig (und sonst würde es nicht funktionieren, weil Sie gegen eine 1.6-Methode kompilieren wollen) und das bedeutet, dass das Programm sorgfältig unter einer 1.5-VM getestet werden sollte, um dieses Problem zu vermeiden. Danke für deine Kommentare von euch beiden.

+0

@Mnementh: ok, aber was würde dann die Reflexions Code aussehen ? – SyntaxT3rr0r

+0

Ich habe meine Antwort so bearbeitet, dass sie den Reflexionscode enthält. – Mnementh

+0

@Mnementh: +1 großartig ... Ich werde versuchen, das heute Nachmittag einzurichten :) – SyntaxT3rr0r

2

Kompilieren Sie für 1.5.

In Ihrem Code verwenden Sie Reflexion. Sie können das Method-Objekt über die Klassenschnittstelle abrufen. Es verfügt über eine Aufrufmethode, die Ihre mbean-Instanz als Parameter verwendet. Etwas wie dieses:

Klasse c = mbean.getClass(); // kann YourClass.class auch tun, um dies zu erhalten

Methode m = c.getMethod ("findMonitorDeadLockedThreads"); // oder ein beliebiges anderes Verfahren

m.invoke (mbean) (Parameter das Verfahren mit Klasse ... zweiten Parameter getMethod angegeben) // ruft die Methode mit Ihrer Instanz

Natürlich Sie don muss das nicht jedes Mal machen; Richten Sie die Methodenreferenzen in einem Konstruktor ein und rufen Sie dann bei Bedarf einfach die richtige Methode auf.

+0

@danpaq: Es ist ein einfacher Fall, da keine Parameter an die Methode übergeben werden müssen. Also von Mnementh und deiner Antwort nehme ich es als Reflexion an, ist der Weg zu gehen ... Also werde ich versuchen, was du hier vorgeschlagen hast. – SyntaxT3rr0r

+0

@WizardOfOdds: Wenn Sie denken, dass dieser Vorschlag wertvoll ist, bitte upvote. –

1

Mit Maven können Sie das ganz einfach mit Profilen machen. Die Idee hinter den Profilen ist, dass Sie basierend auf einigen Kriterien zwei verschiedene Versionen von etwas erstellen möchten. In diesem speziellen Beispiel können Sie ein jdk15 und ein jdk16 Profil definieren, angeben, mit welcher JDK-Version es jeweils zu kompilieren gilt, und eine Kopie der Klasse im jdk15-Profil und die andere in jdk16 angeben.

Um damit zu beginnen, finden Sie unter:

http://unserializableone.blogspot.com/2008/09/compile-and-test-with-different-jdk.html

Diese beschreibt, wie die verschiedenen JDK-Version ein Teil des Problems zu tun.

Um den zweiten Teil des Problems zu behandeln, eine andere Definition der Klasse mit auf der JDK-Version abhängig, sehen:

Maven - Include Different Files at Build Time

+0

Entschuldigung, ich hoffe, dass das hilft ... Ich habe momentan keinen freien Moment, um dir das vollständige maven build script zu zeigen. –

+0

Nur um sicher zu sein, verstehe ich, was du richtig gesagt hast: Ich muss ein einzigartiges * .jar * packen und versenden, das sowohl mit 1.5 als auch mit 1.6 funktioniert, wenn 1.6 verwendet wird. Kann ich das mit den Mave-Profilen machen? – SyntaxT3rr0r

+0

@WizardOfOdds: Ja, das habe ich zuvor versucht zu beschreiben. Ich habe meine Antwort überarbeitet, um Links zu finden, die beschreiben, wie man das besser macht, als ich hier beschreiben könnte. –

Verwandte Themen