2012-12-24 28 views
11

Tôi cố gắng tạo lược tả java đơn giản và sử dụng ClassLoader cho việc này.Trình nạp lớp với yêu cầu RMI

Đây là thực hiện của tôi ClassLoader:

import java.rmi.RemoteException; 
import java.rmi.registry.LocateRegistry; 
import java.rmi.registry.Registry; 

public class CustomClassLoader extends ClassLoader { 
    private Notifier notifier; 

    public CustomClassLoader() { 
     super(); 
    } 

    public CustomClassLoader(ClassLoader parent) { 
     super(parent); 
    } 

    private void initNotifier() { 
     if (notifier != null) return; 
     try { 
      System.out.println("2"); 
      Registry registry = LocateRegistry.getRegistry(Const.registryPort); 
      System.out.println("3"); 
      notifier = (Notifier) registry.lookup(Const.stubName); 
      System.out.println("4"); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } 
    } 

    @Override 
    protected synchronized Class<?> loadClass(String name, boolean resolve) 
            throws ClassNotFoundException { 
     System.out.println("0"); 
     Class clazz = super.loadClass(name, resolve); 
     System.out.println("1"); 
     initNotifier(); 
     System.out.println("5"); 
     try { 
      notifier.classLoaded(name); 
      System.out.println("6"); 
     } catch (RemoteException e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } 
     return clazz; 
    } 
} 

Khi tôi đã cố gắng sử dụng bộ nạp lớp này tôi nhận ra điều này (tôi đã cố gắng sử dụng 1.6_37 và 1.7_10 JKD):

C:\Users\Scepion1d>java -cp C:\Users\Scepion1d\Dropbox\Workspace\IntellijIDEA\pr 
ofiler\out\artifacts\loader\loader.jar;C:\Users\Scepion1d\Dropbox\Workspace\Inte 
llijIDEA\app\out\production\app -Djava.system.class.loader=CustomClassLoader Main 
0 
1 
2 
0 
1 
2 
3 
0 
1 
2 
3 
java.lang.IllegalArgumentException: Non-positive latency: 0 
     at sun.misc.GC$LatencyRequest.<init>(GC.java:190) 
     at sun.misc.GC$LatencyRequest.<init>(GC.java:156) 
     at sun.misc.GC.requestLatency(GC.java:254) 
     at sun.rmi.transport.DGCClient$EndpointEntry.lookup(DGCClient.java:212) 
     at sun.rmi.transport.DGCClient.registerRefs(DGCClient.java:120) 
     at sun.rmi.transport.ConnectionInputStream.registerRefs(ConnectionInputS 
tream.java:80) 
     at sun.rmi.transport.StreamRemoteCall.releaseInputStream(StreamRemoteCal 
l.java:138) 
     at sun.rmi.transport.StreamRemoteCall.done(StreamRemoteCall.java:292) 
     at sun.rmi.server.UnicastRef.done(UnicastRef.java:431) 
     at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source) 
     at CustomClassLoader.initNotifier(CustomClassLoader.java:22) 
     at CustomClassLoader.loadClass(CustomClassLoader.java:35) 
     at java.lang.ClassLoader.loadClass(ClassLoader.java:247) 
     at sun.security.jca.ProviderConfig$3.run(ProviderConfig.java:234) 
     at java.security.AccessController.doPrivileged(Native Method) 
     at sun.security.jca.ProviderConfig.doLoadProvider(ProviderConfig.java:22 
5) 
     at sun.security.jca.ProviderConfig.getProvider(ProviderConfig.java:205) 
     at sun.security.jca.ProviderList.getProvider(ProviderList.java:215) 
     at sun.security.jca.ProviderList.getService(ProviderList.java:313) 
     at sun.security.jca.GetInstance.getInstance(GetInstance.java:140) 
     at java.security.Security.getImpl(Security.java:659) 
     at java.security.MessageDigest.getInstance(MessageDigest.java:129) 
     at java.rmi.dgc.VMID.computeAddressHash(VMID.java:140) 
     at java.rmi.dgc.VMID.<clinit>(VMID.java:27) 
     at sun.rmi.transport.DGCClient.<clinit>(DGCClient.java:66) 
     at sun.rmi.transport.ConnectionInputStream.registerRefs(ConnectionInputS 
tream.java:80) 
     at sun.rmi.transport.StreamRemoteCall.releaseInputStream(StreamRemoteCal 
l.java:138) 
     at sun.rmi.transport.StreamRemoteCall.done(StreamRemoteCall.java:292) 
     at sun.rmi.server.UnicastRef.done(UnicastRef.java:431) 
     at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source) 
     at CustomClassLoader.initNotifier(CustomClassLoader.java:22) 
     at CustomClassLoader.loadClass(CustomClassLoader.java:35) 
     at java.lang.ClassLoader.loadClass(ClassLoader.java:247) 
     at sun.security.jca.ProviderConfig$3.run(ProviderConfig.java:234) 
     at java.security.AccessController.doPrivileged(Native Method) 
     at sun.security.jca.ProviderConfig.doLoadProvider(ProviderConfig.java:22 
5) 
     at sun.security.jca.ProviderConfig.getProvider(ProviderConfig.java:205) 
     at sun.security.jca.ProviderList.getProvider(ProviderList.java:215) 
     at sun.security.jca.ProviderList$3.get(ProviderList.java:130) 
     at sun.security.jca.ProviderList$3.get(ProviderList.java:125) 
     at java.util.AbstractList$Itr.next(AbstractList.java:345) 
     at java.security.SecureRandom.getPrngAlgorithm(SecureRandom.java:522) 
     at java.security.SecureRandom.getDefaultPRNG(SecureRandom.java:165) 
     at java.security.SecureRandom.<init>(SecureRandom.java:133) 
     at java.rmi.server.UID.<init>(UID.java:92) 
     at java.rmi.server.ObjID.<clinit>(ObjID.java:71) 
     at java.rmi.registry.LocateRegistry.getRegistry(LocateRegistry.java:158) 

     at java.rmi.registry.LocateRegistry.getRegistry(LocateRegistry.java:106) 

     at java.rmi.registry.LocateRegistry.getRegistry(LocateRegistry.java:73) 
     at CustomClassLoader.initNotifier(CustomClassLoader.java:20) 
     at CustomClassLoader.loadClass(CustomClassLoader.java:35) 
     at java.lang.ClassLoader.loadClass(ClassLoader.java:247) 

Tôi đã nghĩ rằng vấn đề nằm trong máy chủ RMI, nhưng tôi đã viết một ứng dụng khách RMI khác và nó hoạt động tốt. Có ai biết (các) vấn đề ở đâu và cách giải quyết (chúng)?

+1

Bạn nên thử một phiên bản khác (phiên bản mới hơn hoặc phiên bản khác) và nếu không được, hãy gửi một lỗi (http://bugs.sun.com/) – tcb

+1

Đây thực sự là một lần đệ quy ngẫu nhiên. Có cái nhìn tốt về dấu vết ngăn xếp. Dường như bạn đang lạm dụng trình tải lớp của bạn. – EJP

+0

Để theo dõi nó hơn nữa, bạn cũng có thể thêm 'tên' vào println của bạn cho" 0 ". – JoshDM

Trả lời

2

TL; DR: Không sử dụng trình nạp lớp có tác dụng phụ nặng như trình nạp lớp gốc.

Vấn đề là trường gcInterval const trên lớp sun.rmi.transport.DGCClient không được khởi tạo trước khi nó được sử dụng (và do đó cho thấy giá trị 0). Lý do cho việc này là trình nạp lớp của bạn thực hiện cuộc gọi thông qua RMI tạo ra một cá thể mới của DGCClient. Trong quá trình thực thi hàm tạo của lớp DGCClient, một lớp khác được nạp (xem dấu vết ngăn xếp). Cuộc gọi thứ ba này đến trình nạp lớp sẽ kích hoạt cuộc gọi RMI lần nữa mà không tạo ra một cá thể mới của DGCClient nhưng sử dụng một trình tạo trước đó và thực hiện một số cuộc gọi trên nó. Điều đó có nghĩa rằng một cuộc gọi được thực hiện trên một đối tượng được khởi tạo một nửa dẫn đến việc sử dụng trường liên tục chưa được khởi tạo này.

Chúng tôi không thể đổ lỗi cho Sun/Oracle vì điều này vì mọi lớp Java có thể giả định rằng nó được tải mà không có các tác dụng phụ không thể đoán trước.

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