[英]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.