繁体   English   中英

ClassLoader:如何从另一个项目加载类

[英]ClassLoader: how to load class from another project

我想使用ClassLoader从另一个项目访问一个类。 如何指定该类的路径并获取该类文件?

我希望能够通过代码执行此操作,因为我将通过我的应用程序加载许多不同的类文件,并且不同类的路径将不断变化。

我正在使用CustomClassLoader,它正在加载类文件,但前提是它们在项目中而不在另一个项目中

import java.io.FileInputStream;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;

public class CustomClassLoader extends ClassLoader {

String repoLocation = "C:/TempBINfolder/bin/";

public CustomClassLoader() {
}

public CustomClassLoader(ClassLoader parent) {
    super(parent);
}

@Override
protected Class<?> findClass(final String name)
        throws ClassNotFoundException {

    AccessControlContext acc = AccessController.getContext();

    try {
        return (Class) AccessController.doPrivileged(
                new PrivilegedExceptionAction() {

                    public Object run() throws ClassNotFoundException {

                        FileInputStream fi = null;
                        try {

                            String path = name.replace('.', '/');
                            fi = new FileInputStream(repoLocation + path
                                    + ".class");
                            ByteArrayOutputStream baos = new ByteArrayOutputStream();
                            byte[] buffer = new byte[8192]; // a big chunk
                            int read;
                            while ((read = fi.read(buffer)) > 0)
                                baos.write(buffer, 0, read);
                            byte[] classBytes= baos.toByteArray();

                            return defineClass(name, classBytes, 0,
                                    classBytes.length);
                        } catch (Exception e) {
                            throw new ClassNotFoundException(name);
                        }
                    }
                }, acc);
    } catch (java.security.PrivilegedActionException pae) {
        return super.findClass(name);
    }
}
}

打电话给上课

for (Class singleClass : listOfClasses) {
            try {

                ClassLoader classLoader = new CustomClassLoader(ClassLoader.getSystemClassLoader());
                Class stringClass = null;
                try {
                    stringClass = classLoader.loadClass(singleClass.getName());
                } catch (ClassNotFoundException ex) {
                    Logger.getLogger(CompilerForm.class.getName()).log(Level.SEVERE, null, ex);
                }
                try {
                    stringClass.newInstance();
                } catch (InstantiationException ex) {
                    Logger.getLogger(CompilerForm.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IllegalAccessException ex) {
                    Logger.getLogger(CompilerForm.class.getName()).log(Level.SEVERE, null, ex);
                }


                Class cls = Class.forName(stringClass.getName());

如果我尝试做Class cls = Class.forName(stringClass.getPackage()+"."+stringClass.getName()); 包是null

编辑:以下为我工作

URL classUrl;
classUrl = new URL("file:///"+ccl.getRepoLocation());    //This is location of .class file
URL[] classUrls = {classUrl};
URLClassLoader ucl = new URLClassLoader(classUrls);
Class cls = ucl.loadClass(stringClass.getName());    // Current .class files name

使用URLClassLoader为您完成此操作。

那段代码看起来不错(很久以前我自己做了类似的事)。 还有一个小虫子:

如果你这样做

byte[] classBytes = new byte[fi.available()];
fi.read(classBytes);

您只读取如此多的字节,因为可用字节没有阻塞 是的,你不是在阅读整个文件。 实际上,read方法并不能保证读取完整的字节缓冲区。

试着做:

ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[8192]; // a big chunk
int read;
while ((read = fi.read(buffer)) > 0)
   baos.write(buffer, 0, read);
byte[] bytesClass = baos.toByteArray();

或者使用Apache的Streams.copy 这是一种方便的方法。

包装定义

ClassLoader有一个definePackage方法。 我敢打赌,你应该为你需要的每个新包调用该方法。 否则ClassLoader无法定义一个包,但是从完整的类名来看,它似乎还不够。

所以代码得到这个:

// being package the name of the package for the new class
// being definedPackages a Set<String> member of the classloader

if (!this.definedPackages.contains(package)) {
   definePackage(package,"","","","","","",null);
   this.definedPackages.add(package);
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[8192]; // a big chunk
int read;
while ((read = fi.read(buffer)) > 0)
   baos.write(buffer, 0, read);
byte[] bytesClass = baos.toByteArray();

感谢上面的代码帮助了我。

SUB:在两个不同的位置调用同一个类

我在classpath jar文件中有一个类说Abc并动态地在本地目录中生成相同的类Abc并进行一些代码更改。

我需要创建实例并在本地目录中使用类Abc,下面是工作代码,

class CustomClassLoader扩展ClassLoader {

String repoLocation = "./";
//C:/TempBINfolder/bin/
 CustomClassLoader() {
}

 CustomClassLoader(ClassLoader parent) {
    super(parent);
}

@Override
protected Class<?> findClass(final String name)   throws ClassNotFoundException {

    AccessControlContext acc = AccessController.getContext();

    try {
        return (Class) AccessController.doPrivileged(
                new PrivilegedExceptionAction() {

                    public Object run() throws ClassNotFoundException {

                        FileInputStream fi = null;
                        try {

                            String path = name.replace('.', '/');
                            fi = new FileInputStream(repoLocation + path+ ".class");
                            ByteArrayOutputStream baos = new ByteArrayOutputStream();
                            byte[] buffer = new byte[8192]; // a big chunk
                            int read;
                            while ((read = fi.read(buffer)) > 0)
                                baos.write(buffer, 0, read);
                            byte[] classBytes= baos.toByteArray();

                            return defineClass(name, classBytes, 0,
                                    classBytes.length);
                        } catch (Exception e) {
                            throw new ClassNotFoundException(name);
                        }
                    }
                }, acc);
    } catch (java.security.PrivilegedActionException pae) {
        return super.findClass(name);
    }
}
}

调用CustomClassLoader类,

    ClassLoader classLoader = new CustomClassLoader(ClassLoader.getSystemClassLoader());
    Class stringClass = (new CustomClassLoader(ClassLoader.getSystemClassLoader())).findClass(packageName+"."+javaFileName);
    Object  t = (Object) stringClass.newInstance();

谢谢,Murwath

暂无
暂无

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

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