Nếu câu hỏi của bạn là cách minh họa hoặc hình dung thứ bậc của trình nạp lớp cho các đối tượng, thì bạn có thể đi lên từng lớp trình nạp lớp trong mã. Bạn nói rằng bạn đang sử dụng groovy, vì vậy một ví dụ sẽ trông như thế:
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();
}
}
}
Tôi nghĩ rằng bạn sẽ tìm thấy, trong mã của bạn, hai đối tượng dữ liệu đang thực sự không được nạp từ classloader cùng, đó là lý do họ có các biến tĩnh khác nhau.
Tôi đặt cùng một mẫu có
- Main (nạp từ classloader mẹ)
- DataObj với một static String (nạp cũng từ classloader mẹ)
- LoadA, mà khởi tạo một bản sao của DataObj (được tải từ bộ nạp lớp con A)
- TảiB, tức là bản sao của DataObj (được tải từ bộ nạp lớp con B)
Tôi thấy rằng trong khi LoadA và LoadB có các trình nạp lớp khác nhau, thì DataObj và biến tĩnh đến từ một trình nạp lớp phổ biến.
Toàn mã tại địa chỉ: https://github.com/lucasmcgregor/groovy_classloader_test
Đối tượng chính trong 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);
Kết quả là:
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
Bạn thấy rằng LoadA và LoadB cả hai đều có classloaders khác nhau, nhưng họ chia sẻ trình nạp lớp cha.
Trình nạp lớp cấp độ gốc tải DataObj cho cả hai trường hợp của LoadA.dataObj và LoadB.dataObj.
LoadA.dataObj và LoadB.dataObj có các mã băm khác nhau.
Tuy nhiên, LoadA.dataObj.data và LoadB.dataObj.data có cùng mã băm vì đây là đối tượng tĩnh. Họ cũng có cùng giá trị. LoadB instantiates dữ liệu của nóObj cuối cùng và đặt chuỗi thành "Loaded By B"
Bạn có chắc chắn rằng cả hai 'lớp A' và' lớp B' đang nói chuyện với "cùng" lớp 'Data' như trong - lớp' Data' được nạp bởi một trình nạp lớp đơn? Nếu 'Data' đang được nạp bởi các trình nạp lớp khác nhau và' lớp A' và 'lớp B' đang nói đến các phiên bản khác nhau như vậy, thì những gì bạn đang thấy được mong đợi. Nó phụ thuộc rất nhiều vào hệ thống phân cấp bộ nạp lớp, vì vậy một chút bối cảnh đó sẽ giúp ích. – mystarrocks
@mystarrocks cảm ơn vì phản hồi, điều đó đã giúp ích. Có vẻ như tôi thực sự không có cùng tham chiếu lớp học. Tôi đã cập nhật câu hỏi của mình cho phù hợp. Cám ơn! – WeSt
Các lớp này có thuộc về một ứng dụng đang chạy trên máy chủ không? Các vùng chứa khác nhau sử dụng các kỹ thuật xếp lớp khác nhau. – mystarrocks