Ersetzen Sie eine Klasse in der Java-Klassenbibliothek durch eine benutzerdefinierte Version

9

Die Klasse BasicLabelUI in javax / swing / plaf / basic wird von bestätigter Fehler . In meiner Anwendung brauche ich Funktionalität, die von fixed-Version (für v9 abgelegt) . Aus rechtlichen und technischen Gründen bin ich immer noch an die betroffene JDK-Version gebunden.

Mein Ansatz bestand darin, in meinem Projekt ein Paket javax / swing / plaf / basic zu erstellen, das die korrigierte Version enthält.

Wie kann ich mein Projekt zwingen, meine enthaltene Version der Klasse gegenüber der defekten Klasse im installierten JDK zu bevorzugen?

Dies muss etwas portabel sein, da die feste Klasse auch auf der Kundenseite arbeiten muss und die defekte Klasse in der JDK-Installation ignoriert werden muss. Daher möchte ich das JDK nicht modifizieren, sondern diese spezielle Klasse umgehen.

    
bogus 10.11.2015, 13:42
quelle

2 Antworten

11

Wie in den anderen Antworten erwähnt, können Sie theoretisch die JVM-Datei rt.jar entpacken und die Datei durch eine kompatible Version mit Bugfix ersetzen.

Alle Klassen der Java-Klassenbibliothek, wie jene von Swing, werden vom bootstrap class loader geladen, der seine Klassen von dieser rt.jar abruft. Im Allgemeinen können Sie keine Klassen diesem Klassenpfad voranstellen, ohne sie zu dieser Datei hinzuzufügen. Es gibt eine (nicht standardmäßige) VM-Option

%Vor%

Hier würden Sie eine JAR-Datei voranstellen, die die gepatchte Version enthält, aber dies funktioniert nicht unbedingt auf einer Java Virtual Machine. Außerdem ist es illegal, eine Anwendung zu implementieren, die dieses Verhalten ändert! Wie es in der offiziellen Dokumentation steht:

  

Stellen Sie keine Anwendungen bereit, die diese Option verwenden, um eine Klasse in zu überschreiben   rt.jar, weil dies den Java Runtime Environment-Binärcode verletzt   Lizenz.

Wenn Sie jedoch eine Klasse an den Bootstrap-Klassenlader angehängt haben (was ohne die Verwendung nicht standardmäßiger APIs mithilfe der Instrumentierungs-API möglich ist), lädt die Laufzeitumgebung weiterhin die ursprüngliche Klasse, da der Bootstrap-Klassenlader in diesem Fall nach rt.jar zuerst. Es ist daher unmöglich, die fehlerhafte Klasse zu "beschatten", ohne diese Datei zu ändern.

Schließlich ist es immer illegal, eine VM mit einer gepatchten Datei zu verteilen , dh es in ein Produktionssystem für einen Kunden zu bringen. Die Lizenzvereinbarung besagt eindeutig, dass Sie

müssen
  

[...] verteilt die [Java Laufzeitumgebung] vollständig und unverändert und nur gebündelt als Teil Ihrer Applets und Anwendungen

Das Ändern der VM, die Sie verteilen, wird daher nicht empfohlen, da Sie möglicherweise rechtliche Konsequenzen haben, wenn dies jemals aufgedeckt wird.

Natürlich können Sie theoretisch Ihre eigene Version von OpenJDK erstellen, aber Sie könnten das binäre Java nicht mehr aufrufen, wenn Sie es verteilen, und ich nehme an, dass Ihr Kunde dies nicht durch was zulassen würde Sie schlagen in Ihrer Antwort vor. Aus Erfahrung errechnen viele sichere Umgebungen Hashes von Binaries vor der Ausführung, was beide Ansätze des Optimierens der ausführenden VM verbieten würde.

Die einfachste Lösung für Sie wäre wahrscheinlich die Erstellung eines Java-Agent , den Sie beim Start dem VM-Prozess hinzufügen. Am Ende ist das dem Hinzufügen einer Bibliothek als Klassenpfadabhängigkeit sehr ähnlich:

%Vor%

Ein Java-Agent kann die binäre Darstellung einer Klasse beim Start der Anwendung ersetzen und daher die Implementierung der fehlerhaften Methode ändern.

In Ihrem Fall würde ein Agent etwa wie folgt aussehen, wo Sie die korrigierte Klassendatei als Ressource hinzufügen müssen:

%Vor%

Das Paket javadoc java.lang.instrumentation bietet eine detaillierte Beschreibung zum Erstellen und Implementieren eines Java-Agenten. Mit diesem Ansatz können Sie die feste Version der fraglichen Klasse verwenden, ohne die Lizenzvereinbarung zu verletzen .

Erfahrungsgemäß sind Java-Agenten eine hervorragende Methode, um temporäre Fehler in Bibliotheken von Drittanbietern und in der Java-Klassenbibliothek zu beheben, ohne Änderungen im Code implementieren oder sogar eine neue Version für einen Kunden bereitstellen zu müssen. In der Tat ist dies ein typischer Anwendungsfall für die Verwendung eines Java-Agenten.

    
Rafael Winterhalter 10.11.2015, 13:54
quelle
0
  

Wie kann ich mein Projekt zwingen, meine enthaltene Version der Klasse gegenüber der defekten Klasse im installierten JDK zu bevorzugen?

Einfache Antwort - das geht nicht. Zumindest nicht unter strikter Einhaltung der Einschränkung, dass Sie die betroffene Javs-Version verwenden sollten.

Wenn Sie davon ausgehen, dass Sie eine geeignete Version in den OpenJDK-Quell-Repos identifizieren können, ist es möglich, Ihren eigenen Geschmack der Java-Bibliotheken mit einem gepatchten Bug zu erstellen. Das wird jedoch kein echtes Java sein. Sicher, es wird nicht als "die betroffene Java-Version" eingestuft, die Sie verwenden müssen. (Und außerdem verpflichten Sie sich zu einem endlosen Kreislauf, in dem Sie Ihren Patch erneut auf jedes neue Patch-Release der aktuellen Java-Version anwenden ...)

Es ist theoretisch auch möglich, eine modifizierte Version einer Java-Standardbibliotheksklasse in eine JAR zu schreiben und sie dem Bootstrap-Klassenpfad der JVM mit der Befehlszeilenoption -Xbootclasspath voranzulegen. Das ändert aber auch die "betroffene Java-Version".

Wenn Sie einen Java-Agenten verwenden, um eine gepatchte Version der Klasse zu verwenden, werden die Regeln ebenfalls gebrochen. Und es ist komplizierter.

Wenn Sie und Ihre Kunden entscheiden, dass das Optimieren der JVM eine akzeptable Lösung ist, dann ist es wahrscheinlich der einfachste und sauberste Ansatz, dies über den Bootstrap-Klassenpfad zu tun. Und es ist endgültig legal 1 .

Ich würde jedoch empfehlen, dass Sie eine Problemumgehung für den Fehler finden, bis eine Version von Java 9 mit Ihrem Fix veröffentlicht wird.

1 - Eigentlich ist sogar der Build-from-modified-Source-Ansatz legal, weil die Oracle Binary-Lizenz nicht darauf zutrifft. Die Binary-Lizenz dient zum Verteilen einer modifizierten Version einer Oracle-Binärdatei. Das andere mögliche Problem ist, dass Sie möglicherweise gegen die Bedingungen für die Verwendung der Java-Marke (n) verstoßen, wenn Sie eine Version verteilen, die mit "true" Java inkompatibel ist, und Ihre Distribution "Java" nennen. Die Lösung dazu ist ... nenn es nicht "Java"!

Befolgen Sie jedoch nicht nur meinen Rat. Frage einen Anwalt. Besser noch, tu es überhaupt nicht. Es ist unnötig kompliziert.

    
Stephen C 10.11.2015 13:47
quelle

Tags und Links