Java-自定义类加载器-尝试使用类文件完整路径加载类

Java-自定义类加载器-尝试使用类文件完整路径加载类,java,web-applications,classloader,Java,Web Applications,Classloader,作为用于学术目的的HTTP Web服务器项目的一部分, 我正在尝试为web应用程序类编写自己的自定义类加载器,但似乎做得不对 一般来说,web应用程序位于它们自己的文件夹中,web应用程序的.class文件与其直接父文件夹名称相同。e、 g.Web1/Web1.class。 下面的代码在我达到defineClass方法之前工作正常,然后它抛出我,出现以下异常: java.io.FileNotFoundException:C:\inetpub\javawwwroot\WebApps\java\la

作为用于学术目的的HTTP Web服务器项目的一部分, 我正在尝试为web应用程序类编写自己的自定义类加载器,但似乎做得不对

一般来说,web应用程序位于它们自己的文件夹中,web应用程序的.class文件与其直接父文件夹名称相同。e、 g.Web1/Web1.class。 下面的代码在我达到defineClass方法之前工作正常,然后它抛出我,出现以下异常:

java.io.FileNotFoundException:C:\inetpub\javawwwroot\WebApps\java\lang\Object\.Object.class系统找不到指定的路径

值得一提的是,在下面的代码中,C:\inetpub\javawwwroot\WebApps\part等于m_WebAppsFullPath变量

另外,当尝试使用

InputStream in=getResourceAsStreamclsFile

而不是InputStream in=新文件inputstreamclsfile

我得到一个空的返回值

更新:简而言之,如何加载一个既不在类路径中也不在项目包中的特定类

protected synchronized Class loadClass(String className, boolean resolve) 
                             throws ClassNotFoundException 
{
    log("Loading class: " + className + ", resolve: " + resolve);

    // 1. is this class already loaded?
    Class cls = findLoadedClass(className);
    if (cls != null)
    {
        return cls;
    }

    // 2. get class file name from class name
    String classRelativePath = className.replace('.', '/');
    String classFileName = 
        ((className.lastIndexOf('.') != -1) ? className.substring(className.lastIndexOf('.')) : className) + ".class";

    String clsFile = m_WebAppsFullPath + "\\" + classRelativePath + "\\" + classFileName;

    // 3. get bytes for class
    byte[] classBytes = null;
    try 
    {
        //InputStream in = getResourceAsStream(clsFile);
        InputStream in = new FileInputStream(clsFile);
        byte[] buffer = new byte[BUFFER_SIZE];
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int n = -1;
        while ((n = in.read(buffer, 0, BUFFER_SIZE)) != -1) {
            out.write(buffer, 0, n);
        }
        classBytes = out.toByteArray();
    }
    catch (IOException e) {
        log("ERROR loading class file: " + e);
    }

    if (classBytes == null) {
        throw new ClassNotFoundException("Cannot load class: " + className);
    }

    // 4. turn the byte array into a Class
    try {
        cls = defineClass(className, classBytes, 0, classBytes.length);
        if (resolve) {
            resolveClass(cls);
        }
    }
    catch (SecurityException e) { 
        // loading core java classes such as java.lang.String
        // is prohibited, throws java.lang.SecurityException.
        // delegate to parent if not allowed to load class
        cls = super.loadClass(className, resolve);
    }

    return cls;
}
知道我怎样才能让它工作吗


谢谢

目前,您不仅试图通过自己的类加载器加载自定义类,还尝试加载它们所依赖的所有系统类。比如java.lang.Object,这是您的问题所在

通常,Java中的类加载器是链接的,这意味着您的类加载器已经由另一个类加载器定义,很可能是系统类加载器。因此,建议不要自己覆盖loadClass方法,而是覆盖这两个方法的findClassString:Class和loadClassDataString:Class

下面是Classloader类的Javadoc的一个例外:

ClassLoader类使用委托模型来搜索 课程和资源。ClassLoader的每个实例都有一个 关联的父类加载器。当被要求查找类或 资源,类加载器实例将委托对 在尝试查找前,将类或资源加载到其父类加载器 类或资源本身。虚拟机的内置类加载器, 称为引导类装入器,它本身没有父类,但可能 充当ClassLoader实例的父级

同一个Javadoc甚至列出了一个示例,如何正确定义自定义类加载器:

class NetworkClassLoader extends ClassLoader {
     String host;
     int port;

     public Class findClass(String name) {
         byte[] b = loadClassData(name);
         return defineClass(name, b, 0, b.length);
     }

     private byte[] loadClassData(String name) {
         // load the class data from the connection
          . . .
     }
 }

我想您可能想读一下:

目前,您不仅试图通过自己的类加载器加载自定义类,还试图加载它们所依赖的所有系统类。比如java.lang.Object,这是您的问题所在

通常,Java中的类加载器是链接的,这意味着您的类加载器已经由另一个类加载器定义,很可能是系统类加载器。因此,建议不要自己覆盖loadClass方法,而是覆盖这两个方法的findClassString:Class和loadClassDataString:Class

下面是Classloader类的Javadoc的一个例外:

ClassLoader类使用委托模型来搜索 课程和资源。ClassLoader的每个实例都有一个 关联的父类加载器。当被要求查找类或 资源,类加载器实例将委托对 在尝试查找前,将类或资源加载到其父类加载器 类或资源本身。虚拟机的内置类加载器, 称为引导类装入器,它本身没有父类,但可能 充当ClassLoader实例的父级

同一个Javadoc甚至列出了一个示例,如何正确定义自定义类加载器:

class NetworkClassLoader extends ClassLoader {
     String host;
     int port;

     public Class findClass(String name) {
         byte[] b = loadClassData(name);
         return defineClass(name, b, 0, b.length);
     }

     private byte[] loadClassData(String name) {
         // load the class data from the connection
          . . .
     }
 }

我想您可能想读一下:

如果您能显示完整的异常堆栈跟踪,那会有所帮助….\Object\.Object.class确定您不需要…\Object.class否,我正在尝试加载我自己的名为Web1的类,它位于C:\inetpub\javawwwroot\WebApps\Web1\Web1.class没有如下目录:C:\inetpub\javawwwroot\WebApps\java\lang\n如果您可以显示完整的异常堆栈跟踪…\Object\.Object.class确定您不需要…\Object.class否,我正在尝试加载自己的名为Web1的类,它位于C:\inetpub\javawwwroot\WebApps\Web1\Web1.class。没有像C:\inetpub\javawwwroot\WebApps\java\lang\raven这样的目录是正确的。对于那些定制的find逻辑,应该将其放入findClass方法中。但是基于整个Java类装入器层次结构,它不应该首先尝试从顶级类装入器装入对象类吗?如果失败了,试着用我自己的自定义类加载器加载它?是的。但是,如果您将代码放在findClass和loadClassData中,而不是loadClass中,那么这种行为已经为您解决了;如果您希望父类loadingraven正确,则有必要进行覆盖。对于那些自定义查找逻辑,应该是
但是基于整个Java类加载器层次结构,它不应该首先从顶级类加载器加载对象类吗?如果失败了,试着用我自己的自定义类加载器加载它?是的。但是,如果您将代码放在findClass和loadClassData中,而不是loadClass中,那么这种行为已经为您解决了;如果希望加载父类的最后一个类,则有必要进行覆盖