Se la domanda è come illustrare o visualizzare la gerarchia del classloader per gli oggetti, è possibile risalire a ogni classloader di classi nel codice. Lei ha detto che si sta utilizzando Groovy, quindi un esempio potrebbe essere simile:
def showObjectClassLoaderHierarchy(Object obj) {
def classLoader = showClassLoaderHierarchy(obj.getClass().getClassLoader());
showClassLoaderHierarchy(classLoader);
}
def showClassLoaderHierarchy(ClassLoader loader) {
if (loader != null) {
println "Classloader: " + loader.hashCode();
while (loader.getParent() != null) {
loader = loader.getParent();
println " Child of: " + loader.hashCode();
}
}
}
Penso che troverete, nel codice, i due oggetti di dati sono in realtà non caricati dallo stesso classloader, che è per questo che hanno diverse variabili statiche.
ho messo insieme un campione che ha
- principale (caricato dal classloader genitore)
- DataObj con una stringa statica (caricato anche dal caricamento classe genitore)
- Loada, che crea un'istanza di una copia di DataObj (caricati da bambino classloader a)
- LoadB, che crea un'istanza di una copia di DataObj (caricato dal bambino classloader B)
Vedo che mentre LoadA e LoadB hanno caricatori di classi diversi, DataObj e la variabile statica provengono da un classloader comune.
codice completo a: https://github.com/lucasmcgregor/groovy_classloader_test
l'oggetto principale in Groovy:
import java.lang.ClassLoader;
import java.net.URLClassLoader;
import java.net.URL;
def showObjectClassLoaderHierarchy(Object obj) {
def classLoader = showClassLoaderHierarchy(obj.getClass().getClassLoader());
showClassLoaderHierarchy(classLoader);
}
def showClassLoaderHierarchy(ClassLoader loader) {
if (loader != null) {
println "Classloader: " + loader.hashCode();
while (loader.getParent() != null) {
loader = loader.getParent();
println " Child of: " + loader.hashCode();
}
}
}
println "Setting up child classLoaders A and B...";
def URL[] urlsA = [new URL("file:///tmp/cla/")];
def classLoaderA = new URLClassLoader(urlsA, this.getClass().getClassLoader());
def URL[] urlsB = [new URL("file:///tmp/clb/")];
def classLoaderB = new URLClassLoader(urlsB, this.getClass().getClassLoader());
println "Classloader A heirachry:";
showClassLoaderHierarchy(classLoaderA);
println "Classloader B: ";
showClassLoaderHierarchy(classLoaderB);
println "";
println "Now loading Load classes A and B from seperate classloaders:";
def loadA = classLoaderA.loadClass("LoadA").newInstance();
def loadB = classLoaderB.loadClass("LoadB").newInstance();
print "LoadA: heirachry";
showObjectClassLoaderHierarchy(loadA);
print "LoadB: heirachry";
showObjectClassLoaderHierarchy(loadB);
println "";
println "Now pulling the data objects from both and comparing classloders and static data: ";
def dobjA = loadA.getDataObj();
def dobjB = loadB.getDataObj();
println "dataA static field:" + dobjA.getData();
println "dataA static field hashcode: " + dobjA.getData().hashCode();
println "dataA hashcode: " + dobjA.hashCode();
println "dataA classloader: ";
showObjectClassLoaderHierarchy(dobjA);
println "dataB static field: " + dobjB.getData();
println "dataB static field hashcode: " + dobjB.getData().hashCode();
println "dataB hashcode: " + dobjB.hashCode();
println "dataB classLoader:";
showObjectClassLoaderHierarchy(dobjB);
I risultati sono:
Setting up child classLoaders A and B...
Classloader A heirachry:
Classloader: 1926764753
Child of: 1163157884
Child of: 1022308509
Classloader B:
Classloader: 846238611
Child of: 1163157884
Child of: 1022308509
Now loading Load classes A and B from seperate classloaders:
LoadA: heirachryClassloader: 1926764753
Child of: 1163157884
Child of: 1022308509
LoadB: heirachryClassloader: 846238611
Child of: 1163157884
Child of: 1022308509
Now pulling the data objects from both and comparing classloders and static data:
dataA static field:Loaded By B
dataA static field hashcode: 1828548084
dataA hashcode: 2083117811
dataA classloader:
Classloader: 1163157884
Child of: 1022308509
dataB static field: Loaded By B
dataB static field hashcode: 1828548084
dataB hashcode: 157683534
dataB classLoader:
Classloader: 1163157884
Child of: 1022308509
Si vede che Loada e LoadB entrambi hanno diverse classloader, ma condividi un classloader genitore.
Il programma di caricamento classe genitore carica DataObj per entrambe le istanze di LoadA.dataObj e LoadB.dataObj.
LoadA.dataObj e LoadB.dataObj hanno hash diversi.
Tuttavia, LoadA.dataObj.data e LoadB.dataObj.data hanno lo stesso codice hash, poiché questo è l'oggetto statico. Hanno anche lo stesso valore. LoadB crea l'istante di dataObj e imposta la stringa su "Caricato da B"
Sei sicuro che sia la 'classe A' sia la' classe B' stanno parlando al "same" 'Data' class as in - la classe' Data' caricata da un singolo classloader? Se 'Data' viene caricato da diversi programmi di caricamento classi e' classe A' e 'classe B' stanno parlando con diverse versioni di questo tipo, allora quello che vedi è previsto. Dipende molto dalla gerarchia del classloader, quindi un po 'di quel contesto ti aiuterà. – mystarrocks
@mystarrocks grazie per il feedback, che ha già aiutato. Sembra che davvero non ottenga lo stesso riferimento di classe. Ho aggiornato la mia domanda di conseguenza. Grazie! – WeSt
Queste classi appartengono a un'applicazione in esecuzione su un server? Diversi contenitori utilizzano diverse tecniche di classloading. – mystarrocks