2016-04-03 9 views
0

Also habe ich meine eigene Classloader-Klasse ServerLoader, die Klassen vom lokalen Server mit Pfad http://localhost/app/1/ laden kann, wo einige .class-Dateien existieren. Aber mein Programm stürzt ab, wenn ich versuche, den Byte-Code einer Klasse zu definieren.Ausnahme im Thread "main" java.lang.NoClassDefFoundError: java/lang/Objekt

result = defineClass(name, ByteClass, 0, ByteClass.length); 

So erhalte ich eine Exception in thread "main" java.lang.NoClassDefFoundError: java/lang/Object

Hier ist die ganze Klasse:

package com.local; 

import java.io.*; 
import java.net.HttpURLConnection; 
import java.net.URL; 
import java.security.MessageDigest; 
import java.security.NoSuchAlgorithmException; 
import java.util.HashMap; 
import java.util.Map; 

public class ServerLoader extends ClassLoader { 

    private ClassLoader parent; 
    private String urlPath; 

    public ServerLoader(String urlPath) { 
     parent = ServerLoader.class.getClassLoader(); 
     this.urlPath = urlPath; 
    } 

    @Override 
    public Class<?> loadClass(String name) throws ClassNotFoundException { 

     Class<?> result = null; 

     try { 
      URL mainUrl = new URL(urlPath + name.substring(11); 
      HttpURLConnection conn = (HttpURLConnection) mainUrl.openConnection(); 
      conn.setRequestMethod("GET"); 

      ByteArrayOutputStream out = new ByteArrayOutputStream(); 
      BufferedInputStream input = new BufferedInputStream(conn.getInputStream()); 

      int data; 
      while ((data = input.read()) != -1) { 
       out.write(data); 
      } 

      byte[] ByteClass = out.toByteArray(); 
      result = defineClass(name, ByteClass, 0, ByteClass.length); 
      cacheClass.put(result.getName(), result); 
      return result; 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     return null; 
    } 

}  

So, hier ist Hauptmethode

package com.local; 

import java.lang.reflect.Method; 

public class Main { 

    public static void main(String[] args) throws Exception { 
     ServerLoader loader = new ServerLoader("http://localhost/app/1/"); 

     Class<?> remoteInstanceClass = loader.loadClass("com.server.PluginA"); 

     Method mainMethod = remoteInstanceClass.getMethod("main", String[].class); 
     mainMethod.invoke(remoteInstanceClass, (Object) args); 
    } 
} 

Und Stack-Trace

com.local.Main 
    Connected to the target VM, address: '127.0.0.1:54553', transport: 'socket' 
    java.io.FileNotFoundException: http://localhost/app/1/Object.class 
     at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1836) 
     at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441) 
     at com.local.ServerLoader.ConnectAndResolveClass(ServerLoader.java:43) 
     at com.local.ServerLoader.loadClass(ServerLoader.java:28) 
     at java.lang.ClassLoader.defineClass1(Native Method) 
     at java.lang.ClassLoader.defineClass(ClassLoader.java:763) 
     at java.lang.ClassLoader.defineClass(ClassLoader.java:642) 
     at com.local.ServerLoader.ConnectAndResolveClass(ServerLoader.java:51) 
     at com.local.ServerLoader.loadClass(ServerLoader.java:28) 
     at com.local.Main.main(Main.java:10) 
    Exception in thread "main" java.lang.NoClassDefFoundError: java/lang/Object 
     at java.lang.ClassLoader.defineClass1(Native Method) 
     at java.lang.ClassLoader.defineClass(ClassLoader.java:763) 
     at java.lang.ClassLoader.defineClass(ClassLoader.java:642) 
     at com.local.ServerLoader.ConnectAndResolveClass(ServerLoader.java:51) 
     at com.local.ServerLoader.loadClass(ServerLoader.java:28) 
     at com.local.Main.main(Main.java:10) 
    Disconnected from the target VM, address: '127.0.0.1:54553', transport: 'socket' 

Process finished with exit code 1 

Alle Pfade und Namen sind korrekt. Was kann das Problem verursachen?

+0

Wenn die Pfadnamen korrekt sind, sagen Sie, dass die Datei 'http: // localhost/app/1/Object.class' existiert? Ansonsten sind die Pfade nicht korrekt. –

+0

Was ist ein Beispiel für eine Klasse, die funktioniert? –

Antwort

0

Ich löste dieses Problem. Jeder ClassLoader in der Methode LoadClass muss zuerst die Klasse mit dem übergeordneten ClassLoader laden und dann versuchen, sie auf andere Weise zu laden. Das ist also die LoadClass-Methode.

@Override 
public Class<?> loadClass(String name) throws ClassNotFoundException { 

    Class<?> result = null; 

    try { 
     result = parent.loadClass(name); 
    } catch (ClassNotFoundException e) { 
     try { 
      URL mainURL = new URL(urlPath + name.substring(name.lastIndexOf('.') + 1) + ".class"); 
      HttpURLConnection conn = (HttpURLConnection) mainURL.openConnection(); 
      conn.setRequestMethod("GET"); 

      ByteArrayOutputStream out = new ByteArrayOutputStream(); 
      BufferedInputStream input = new BufferedInputStream(conn.getInputStream()); 

      int data; 
      while ((data = input.read()) != -1) { 
       out.write(data); 
      } 

      byte[] byteClass = out.toByteArray(); 
      result = defineClass(name, byteClass, 0, byteClass.length); 

     } catch (IOException e1) { 
      e1.printStackTrace(); 
     } 
    } 

    return result; 
} 

Sie gefragt Beispielklasse:

package com.server; 

public class PluginE { 
    public static void main(String[] args) { 
     System.out.println("Executing main method of PluginE"); 

    } 
}