简体   繁体   English

Java自定义类加载器

[英]Java Custom Class Loader

Any ideas why I am getting this error? 任何想法为什么我会收到此错误? (Yes, I looked up the error, and still haven't found a solution) (是的,我查找了错误,但仍未找到解决方案)

My error: 我的错误:

Exception in thread "main" java.lang.ClassFormatError: Truncated class file
 at java.lang.ClassLoader.defineClass1(Native Method)
 at java.lang.ClassLoader.defineClass(Unknown Source)
 at java.lang.ClassLoader.defineClass(Unknown Source)
 at org.fellixombc.mysql.util.MysqlClassLoader.findClass(MysqlClassLoader.java:22)
 at org.fellixombc.mysql.util.MysqlClassLoader.loadClass(MysqlClassLoader.java:14)
 at org.fellixombc.mysql.Main.main(Main.java:9)

Files: 文件:

Main.java Main.java

package org.fellixombc.mysql;

import org.fellixombc.mysql.util.MysqlClassLoader;

public class Main {
    public static void main(String[] args) {
        MysqlClassLoader mcl = new MysqlClassLoader();
        try {
            mcl.loadClass("org.fellixombc.mysql.net.Client");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

Client.java: Client.java:

package org.fellixombc.mysql.net;

public class Client {
    public Client() {
        System.out.println("Hello!");
    }
}

MysqlClassLoder.java: MysqlClassLoder.java:

package org.fellixombc.mysql.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class MysqlClassLoader extends ClassLoader {
    public MysqlClassLoader() {
        super(MysqlClassLoader.class.getClassLoader());
    }

    @Override
    public Class<?> loadClass(String className) throws ClassNotFoundException {
        return findClass(className);
    }

    @Override
    public Class<?> findClass(String className) throws ClassNotFoundException {
        byte[] b = null;
        try {
            b = loadClassData(className);
            Class c = defineClass(className, b, 0, b.length);
            if(c != null)
                return c;
            return super.findClass(className);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private byte[] loadClassData(String className) throws IOException {
        int size = className.length();
        byte buff[] = new byte[size];

        // Open the file
        FileInputStream fis = new FileInputStream("bin/" + className.replace('.', File.separatorChar) + ".class");
        fis.available();
        fis.read(buff);
        fis.close();

        return buff;
    }
}

Yes, you're reading at most a byte count equal to the number of characters in the filename. 是的,您最多读取的字节数等于文件名中的字符数。 Instead, you need to read the whole file. 相反,您需要读取整个文件。 Here's one method, using readFully as you suggested. 这是一种方法,按照您的建议使用readFully。

File f = new File("bin/" + className.replace('.', File.separatorChar) + ".class");
DataInputStream is = new DataInputStream(new FileInputStream(f));
int len = (int)f.length();
byte[] buff = new byte[len];
is.readFully(buff);
is.close();
return buff;

Since you're not handling built-in classes like Object, I think you need to catch the FileNotFoundException from loadClassData in your findClass, then call super.findClass. 由于您不处理诸如Object之类的内置类,因此我认为您需要从findClass中的loadClassData捕获FileNotFoundException,然后调用super.findClass。 Eg: 例如:

try {
  try {
    b = loadClassData(className);
  }
  catch(FileNotFoundException fnf) {
    return super.findClass(className);
  }
  Class c = defineClass(className, b, 0, b.length);
  if(c != null)
    return c;
  return super.findClass(className);
} catch (IOException e) {
  e.printStackTrace();
}
return null;

You are reading only N bytes (N=length of class name) from the .class file into the buffer (in loadClassData) before returning it. 您只能从.class文件中将N个字节(N =类名的长度)读取到缓冲区(在loadClassData中)之前,将其返回。

You need to read the contents of the entire class before you return the buffer for the class to be properly defined. 您需要先读取整个类的内容,然后再返回要正确定义的类的缓冲区。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM