Come accennato da parte delle altre risposte, si potrebbe in teoria, naturalmente, decomprimere rt.jar file del JVM e sostituire il file con una versione bugfixed compatibili.
Eventuali classi della libreria Java di classe come quelli di Swing vengono caricati dalla classe bootstrap loader che guarda le sue classi da questo rt.jar. Generalmente non è possibile aggiungere le classi a questo percorso di classe senza aggiungerle a questo file. C'è un'opzione (non standard) VM
-Xbootclasspath/jarWithPatchedClass.jar:path
dove si sarebbe anteporre un file jar che include la versione patchata, ma questo non significa necessariamente lavorare su qualsiasi macchina virtuale Java. Inoltre, è illegale distribuire un'applicazione che modifica questo comportamento! Come si afferma nella official documentation:
Non distribuire le applicazioni che utilizzano questa opzione per sostituire una classe in rt.jar perché questo viola il codice binario licenza Java Runtime Environment.
Se invece annesse una classe alla classe bootstrap loader (ciò che è possibile senza utilizzare API non standard utilizzando l'API strumentazione), il runtime sarebbe ancora caricare la classe originale come classe bootstrap loader in questo caso cerca prima il rt.jar. È quindi impossibile "oscurare" la classe rotta senza modificare questo file.
Infine, è sempre illegal to distribute a VM with a patched file, ovvero lo inserisce in un sistema di produzione per un cliente. Il contratto di licenza afferma chiaramente che è necessario
[...] distribuire il [runtime Java] completo e non modificato in pacchi solo come una parte del tuo applet e applicazioni
Modifica della VM che si distribuire è quindi sconsigliato in quanto si potrebbero affrontare conseguenze legali quando questo è mai scoperto.
Naturalmente, è possibile, in teoria, costruire la propria versione della OpenJDK, ma non si può chiamare l'binario Java più quando si distribuisce e presumo che il vostro cliente non avrebbe permesso a questo da quello che lei suggerisce nella vostra risposta. Per esperienza, molti ambienti sicuri calcolano gli hash dei binari prima dell'esecuzione, cosa che proibirebbe entrambi gli approcci di modificare la VM in esecuzione.
La soluzione più semplice per voi sarebbe probabilmente la creazione di un Java agent che si aggiunge al processo VM all'avvio. Alla fine, questo è molto simile all'aggiunta di una libreria come dipendenza percorso classe:
java -javaagent:bugFixAgent.jar -jar myApp.jar
offerente A Java è in grado di sostituire rappresentazione binaria di una classe quando si avvia l'applicazione e può quindi modificare l'implementazione del passeggino metodo.
Nel tuo caso, un agente sarebbe simile a quanto segue dove è necessario includere il file di classe patch come ressource:
public static class BugFixAgent {
public static void premain(String args, Instrumentation inst) {
inst.addClassFileTransformer(new ClassFileTransformer() {
@Override
public byte[] transform(ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer) {
if (className.equals("javax/swing/plaf/basic/BasicLabelUI")) {
return patchedClassFile; // as found in the repository
// Consider removing the transformer for future class loading
} else {
return null; // skips instrumentation for other classes
}
}
});
}
}
Il pacchetto Javadoc java.lang.instrumentation
offre una descrizione dettagliata di come costruire e implementare un agente Java. Utilizzando questo approccio, è possibile utilizzare la versione fissa della classe in questione senza interrompere il contratto di licenza.
Per esperienza, gli agenti Java sono un ottimo modo per correggere bug temporanei nelle librerie di terze parti e nella libreria di classi Java senza la necessità di distribuire le modifiche nel codice o di richiedere la distribuzione di una nuova versione per un cliente. Di fatto, questo è un tipico caso d'uso per l'utilizzo di un agente Java.
Stranamente, non riesco a riprodurre questo errore in Java 1.7.0_75 o 1.8.0_65, in Windows 7, utilizzando il codice dall'invio del bug. Ho provato a modificarlo per usare il look-and-feel di default; Ho provato ad aggiungere l'uso di EventQueue.invokeLater al metodo principale. (Speravo di sperimentare una soluzione alternativa basata su InputMap.) – VGR
Posso riprodurre il comportamento errato utilizzando il codice da http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7172652. Sto usando 1.8.0_45 – bogus