2016-04-03 7 views
0

Итак, у меня есть свой класс classloader class ServerLoader, который может загружать классы с локального сервера с помощью пути http://localhost/app/1/, где есть некоторые .class-файлы. Но моя программа падает, когда я пытаюсь определить байтовый код некоторого класса.Исключение из потока «main» java.lang.NoClassDefFoundError: java/lang/Object

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

Так я получаю Exception in thread "main" java.lang.NoClassDefFoundError: java/lang/Object

Вот весь класс:

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; 
    } 

}  

Так вот главный метод

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); 
    } 
} 

и трассировки стека

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 

Все исправления и правильные имена. Так что может вызвать проблему?

+0

Если имена путей являются правильными, вы говорите, что файл 'HTTP: // локальный/приложение/1/Object.class' существует? В противном случае пути неверны. –

+0

Что такое класс, который работает? –

ответ

0

Я решил эту проблему. Каждый ClassLoader в методе LoadClass должен сначала загрузить класс, используя родительский ClassLoader, а затем попытаться загрузить его по-другому. Итак, это правильный метод LoadClass.

@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; 
} 

Вы спрашивали о примере класса:

package com.server; 

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

    } 
}