2012-12-24 12 views
11

Ich versuche, einfach Java-Profiler zu machen und ClassLoader dafür zu verwenden.ClassLoader mit RMI-Aufruf

Dies ist meine Implementierung von 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; 
    } 
} 

Wenn ich habe versuchen, diese Klassenlade ich diese Ausgabe erhalten zu verwenden (ich habe versucht 1.6_37 und 1.7_10 jkd zu verwenden):

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) 

Ich habe gedacht, dass das Problem in der RMI-Server ist, aber ich schrieb einen anderen RMI-Client und es funktioniert gut. Weiß jemand, wo ist das Problem (s) und wie man es (sie) löst?

+1

Sie sollten eine andere (neuere oder andere Version) Java versuchen und wenn es nicht hilft, dann senden Sie einen Fehler (http://bugs.sun.com/) – tcb

+1

Dies ist wirklich eine versehentliche Rekursion. Werfen Sie einen guten Blick auf die Stack-Trace. Sie scheinen Ihren Klassenlader zu sehr zu benutzen. – EJP

+0

Um es weiter zu verfolgen, können Sie auch 'name' zu ​​Ihrem Ausdruck für" 0 "hinzufügen. – JoshDM

Antwort

2

TL; DR: Verwenden Sie keinen Klassenlader, der so starke Nebenwirkungen hat wie der Root-Klassenlader.

Das Problem ist, dass das const-Feld gcInterval in der Klasse sun.rmi.transport.DGCClient nicht initialisiert wird, bevor es verwendet wird (und daher den Wert 0 anzeigt). Der Grund dafür ist, dass Ihr Klassenlader den Aufruf über RMI ausführt, der eine neue Instanz von DGCClient erstellt. Während der Ausführung des Konstruktors von DGCClient wird eine andere Klasse geladen (siehe Stack-Trace). Dieser dritte Aufruf an den Klassenlader löst den RMI-Aufruf erneut aus, der keine neue Instanz von DGCClient erstellt, sondern die zuvor erstellte Instanz verwendet und einige Aufrufe darauf aufruft. Dies bedeutet, dass ein Aufruf an einem halb initialisierten Objekt erfolgt, was zur Verwendung dieses noch nicht initialisierten Konstantenfeldes führt.

Wir können Sun/Oracle nicht dafür verantwortlich machen, da jede Java-Klasse davon ausgehen kann, dass sie ohne solche unvorhersehbaren Nebenwirkungen geladen wird.