[英]ClassLoader: how to load class from another project
I want to access a class from another project using ClassLoader. 我想使用ClassLoader从另一个项目访问一个类。 How can I specify the path to that class and get that class file?
如何指定该类的路径并获取该类文件?
I want to be able to do this through code as I will be loading many different class files through my application and the path for the different classes will be constantly changing. 我希望能够通过代码执行此操作,因为我将通过我的应用程序加载许多不同的类文件,并且不同类的路径将不断变化。
I am using a CustomClassLoader which is loading class files but only if they are in the project and not in another project 我正在使用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);
}
}
}
Calling the class 打电话给上课
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());
If i try to do Class cls = Class.forName(stringClass.getPackage()+"."+stringClass.getName());
如果我尝试做
Class cls = Class.forName(stringClass.getPackage()+"."+stringClass.getName());
the package is null
包是
null
EDIT: The following worked for me 编辑:以下为我工作
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为您完成此操作。
That code looks good (I've myself did something similar a long time ago). 那段代码看起来不错(很久以前我自己做了类似的事)。 Altough there's a little bug:
还有一个小虫子:
If you do 如果你这样做
byte[] classBytes = new byte[fi.available()];
fi.read(classBytes);
You are only reading so many bytes as bytes available with no blocking are. 您只读取如此多的字节,因为可用字节没有阻塞 。 It is, you're not reading the whole file.
是的,你不是在阅读整个文件。 In fact, read method doesn't assure the complete byte buffer will be read.
实际上,read方法并不能保证读取完整的字节缓冲区。
Try to do: 试着做:
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();
or use Streams.copy from Apache. 或者使用Apache的Streams.copy 。 It's a convenience method to do the same.
这是一种方便的方法。
Package definition 包装定义
ClassLoader has a definePackage
method. ClassLoader有一个
definePackage
方法。 I'd bet that you should call that method for every new package you need. 我敢打赌,你应该为你需要的每个新包调用该方法。 Otherwise ClassLoader has no way to define a package but from the full classname and it seems it's not enough.
否则ClassLoader无法定义一个包,但是从完整的类名来看,它似乎还不够。
So code get to this: 所以代码得到这个:
// 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();
Thanks for the Above Code which Helped me . 感谢上面的代码帮助了我。
SUB : calling same class available in two different locations SUB:在两个不同的位置调用同一个类
I have a class say Abc in classpath jar file and dynamically I generate the same class Abc in local directory with some code changes. 我在classpath jar文件中有一个类说Abc并动态地在本地目录中生成相同的类Abc并进行一些代码更改。
I need to create instance and use the class Abc in local directory , Below is the Working Code , 我需要创建实例并在本地目录中使用类Abc,下面是工作代码,
class CustomClassLoader extends ClassLoader { 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);
}
}
}
calling the CustomClassLoader class, 调用CustomClassLoader类,
ClassLoader classLoader = new CustomClassLoader(ClassLoader.getSystemClassLoader());
Class stringClass = (new CustomClassLoader(ClassLoader.getSystemClassLoader())).findClass(packageName+"."+javaFileName);
Object t = (Object) stringClass.newInstance();
Thanks, Murwath 谢谢,Murwath
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.