2013-04-30 40 views
7

mục tiêu cuối cùng của tôi là có thể tải lại các lớp sau khi chúng đã được nạp vào JVM.Dỡ bỏ bộ nạp lớp

Sau khi đọc câu trả lời sau Unloading classes in java?, tôi đã cố gắng triển khai Trình tải lớp của riêng mình, bản thân nó tạo ra một thể hiện khác của Trình nạp lớp (cùng loại riêng của nó) cho mỗi lớp mà nó tải.

vì vậy, kết quả là một lớp cho mỗi Trình tải lớp.

Mục đích là để có thể GC lớp, có nghĩa là tất cả các trường hợp của nó, sau đó để bỏ tải lớp của nó, và để có thể tải lại cùng một lớp từ các byte của nó.

vấn đề là - tôi có thể thấy trường hợp của tôi là rác được thu thập bằng phương thức finalize(), nhưng tôi không thể lấy Trình nạp lớp để tải hoặc bị thu gom rác.
là có bất kỳ ví dụ mã nào, một thử nghiệm đơn giản, cho thấy nó có thể được thực hiện như thế nào?

cảm ơn, bất kỳ trợ giúp sẽ được đánh giá cao

Sửa:

để được rõ ràng hơn, tôi đang quan tâm trong các ví dụ mã nơi instantiation của các đối tượng mới là thông qua 'mới()' toán hạng và Trình nạp lớp không tải lại rõ ràng Lớp trong chính, nhưng sau khi hàm 'new()' mới được gọi.

+0

Khi bạn tải một lớp thông qua một 'Lớp nạp 'tùy chỉnh, bạn sẽ nhận được một đối tượng' Lớp'. Không thể sử dụng toán tử 'new' với điều đó. Sử dụng 'new' ngụ ý rằng mã của bạn đã được liên kết với lớp được sử dụng bởi' new' và do đó, lớp không thể thu gom rác khi mã của bạn chứa biểu thức 'mới' vẫn hoạt động. Bạn phải sử dụng Phản ánh tại thời điểm này, ví dụ: gọi 'newInstance()' trên 'Lớp'. Tất nhiên, mã được nạp động có thể tự sử dụng 'new' để khởi tạo các lớp trong phạm vi riêng của nó. – Holger

Trả lời

9

Trình tải lớp nên được thu thập rác nếu không có thêm tham chiếu đến chúng. Tôi mất this code từ @PeterLawrey (nhờ) (nó làm điều tương tự như của bạn), hãy đặt một bản ghi trong lớp tùy chỉnh phương pháp nạp finalize() và thì đấy, các bộ tải lớp được thu gom rác sau giờ học tải của họ là gc:

/* Copyright (c) 2011. Peter Lawrey 
* 
* "THE BEER-WARE LICENSE" (Revision 128) 
* As long as you retain this notice you can do whatever you want with this stuff. 
* If we meet some day, and you think this stuff is worth it, you can buy me a beer in return 
* There is no warranty. 
*/ 


import java.lang.reflect.Field; 
import java.net.URL; 
import java.net.URLClassLoader; 

public class LoadAndUnloadMain { 
    public static void main(String... args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InterruptedException { 
     URL url = LoadAndUnloadMain.class.getProtectionDomain().getCodeSource().getLocation(); 
     final String className = LoadAndUnloadMain.class.getPackage().getName() + ".UtilityClass"; 
     { 
      ClassLoader cl; 
      Class clazz; 

      for (int i = 0; i < 2; i++) { 
       cl = new CustomClassLoader(url); 
       clazz = cl.loadClass(className); 
       loadClass(clazz); 

       cl = new CustomClassLoader(url); 
       clazz = cl.loadClass(className); 
       loadClass(clazz); 
       triggerGC(); 
      } 
     } 
     triggerGC(); 
    } 

    private static void triggerGC() throws InterruptedException { 
     System.out.println("\n-- Starting GC"); 
     System.gc(); 
     Thread.sleep(100); 
     System.out.println("-- End of GC\n"); 
    } 

    private static void loadClass(Class clazz) throws NoSuchFieldException, IllegalAccessException { 
     final Field id = clazz.getDeclaredField("ID"); 
     id.setAccessible(true); 
     id.get(null); 
    } 

    private static class CustomClassLoader extends URLClassLoader { 
     public CustomClassLoader(URL url) { 
      super(new URL[]{url}, null); 
     } 

     @Override 
     protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { 
      try { 
       return super.loadClass(name, resolve); 
      } catch (ClassNotFoundException e) { 
       return Class.forName(name, resolve, LoadAndUnloadMain.class.getClassLoader()); 
      } 
     } 

     @Override 
     protected void finalize() throws Throwable { 
      super.finalize(); 
      System.out.println(this.toString() + " - CL Finalized."); 
     } 
    } 
} 

class UtilityClass { 
    static final String ID = Integer.toHexString(System.identityHashCode(UtilityClass.class)); 
    private static final Object FINAL = new Object() { 
     @Override 
     protected void finalize() throws Throwable { 
      super.finalize(); 
      System.out.println(ID + " Finalized."); 
     } 
    }; 

    static { 
     System.out.println(ID + " Initialising"); 
    } 
} 
+0

Cảm ơn, tôi đã quan tâm nhiều hơn đến các ví dụ mã hiển thị tức thời các lớp thông qua toán hạng 'mới()', xin lỗi vì không rõ ràng trong câu hỏi của tôi, tôi sẽ chỉnh sửa nó. –

1

Trong IBM J9 VM mọi thứ khác với việc tải lớp học chỉ xảy ra trong một gc toàn cầu. Điều này có thể dẫn đến thời gian tạm dừng lớn trong gc toàn cầu và hết bộ nhớ khi có một số lượng lớn các bộ nạp lớp học đang được tạo ra . Tôi đã gặp phải vấn đề này với JMXMP trong đó một phiên bản của bộ nạp lớp com.sun.jmx.remote.opt.util.OrderClassLoaders được tạo cho mỗi thông báo từ xa thuộc loại MBeanServerRequestMessage.CREATE_MBEAN_LOADER_PARAMS.

Các vấn đề liên quan