java 运行 加载jar,java运行时加载额外的 jar 包或 class
首先講下java類加載的順序
每個類加載器有自己的名字空間,對于同一個類加載器實例來說,名字相同的類只能存在一個,并且僅加載一次。不管該類有沒有變化,下次再需要加載時,它只是從自己的緩存中直接返回已經加載過的類引用。
接下來講如何加載外部jar
首先要有一個工程外的jar包,這里假定有個Test.jar,里面有個com.chentaoqian.test.Test類。
使用系統類加載器,加載一個jar
Java
package com.chentaoqian.classloaderdemo;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
public class MyClassloader {
public static void classLoader(File file, String className, String methodName, Object[] args, Class>[] parameterTypes) {
try {
URL url = file.toURI().toURL();
//得到系統類加載器,利用該加載器加載指定路徑下的jar包
URLClassLoader urlClassLoader= (URLClassLoader) ClassLoader.getSystemClassLoader();
Method add = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{ URL.class});
add.setAccessible(true);
add.invoke(urlClassLoader, new Object[] {url});
urlClassLoader.loadClass(className);
Class> c = urlClassLoader.loadClass(className);
//列出所有方法
// Method[] methods = c.getMethods();
// for (Method m : methods) {
// System.out.println(m.getName());
// }
//調用方法
// if (args == null) {
// c.getMethod(methodName, parameterTypes).invoke(c.newInstance());
// } else {
// c.getMethod(methodName, parameterTypes).invoke(c.newInstance(), args);
// }
// urlClassLoader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
//無參方法的例子
classLoader(new File("E:\\TestJar.jar"), "com.chentaoqian.test.Test", "sayHi", null, null);
//有參方法的例子
classLoader(new File("E:\\TestJar.jar"), "com.chentaoqian.test.Test", "sayBye", new String[]{"byebye"}, new Class>[]{String.class});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
packagecom.chentaoqian.classloaderdemo;
importjava.io.File;
importjava.lang.reflect.Method;
importjava.net.URL;
importjava.net.URLClassLoader;
publicclassMyClassloader{
publicstaticvoidclassLoader(Filefile,StringclassName,StringmethodName,Object[]args,Class>[]parameterTypes){
try{
URLurl=file.toURI().toURL();
//得到系統類加載器,利用該加載器加載指定路徑下的jar包
URLClassLoaderurlClassLoader=(URLClassLoader)ClassLoader.getSystemClassLoader();
Methodadd=URLClassLoader.class.getDeclaredMethod("addURL",newClass[]{URL.class});
add.setAccessible(true);
add.invoke(urlClassLoader,newObject[]{url});
urlClassLoader.loadClass(className);
Class>c=urlClassLoader.loadClass(className);
//列出所有方法
//??????????Method[] methods = c.getMethods();
//??????????for (Method m : methods) {
//??????????????System.out.println(m.getName());
//??????????}
//調用方法
//??????????if (args == null) {
//??????????????c.getMethod(methodName, parameterTypes).invoke(c.newInstance());
//??????????} else {
//??????????????c.getMethod(methodName, parameterTypes).invoke(c.newInstance(), args);
//??????????}
//??????????urlClassLoader.close();
}catch(Exceptione){
e.printStackTrace();
}
}
publicstaticvoidmain(String[]args){
//無參方法的例子
classLoader(newFile("E:\\TestJar.jar"),"com.chentaoqian.test.Test","sayHi",null,null);
//有參方法的例子
classLoader(newFile("E:\\TestJar.jar"),"com.chentaoqian.test.Test","sayBye",newString[]{"byebye"},newClass>[]{String.class});
}
}
使用jdk自帶的classloader,可以正確的加載jar包中的指定class,但如果要加載單獨的一個class文件,則會報錯。
使用自定義類加載器,加載一個class
通過編寫一個類繼承自ClassLoader,并重寫findClass方法
package com.chentaoqian.classloaderdemo;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
public class MyClassloader2 extends ClassLoader {
private String fileName;
public MyClassloader2(String fileName) {
this.fileName = fileName;
}
@Override
protected Class> findClass(String name) throws ClassNotFoundException {
File file = new File(fileName);
try {
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int len = 0;
while ((len = fis.read()) != -1) {
bos.write(len);
}
byte[] data = bos.toByteArray();
fis.close();
bos.close();
return defineClass(name, data, 0, data.length);
} catch (Exception ex) {
ex.printStackTrace();
}
return super.findClass(name);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
packagecom.chentaoqian.classloaderdemo;
importjava.io.ByteArrayOutputStream;
importjava.io.File;
importjava.io.FileInputStream;
publicclassMyClassloader2extendsClassLoader{
privateStringfileName;
publicMyClassloader2(StringfileName){
this.fileName=fileName;
}
@Override
protectedClass>findClass(Stringname)throwsClassNotFoundException{
Filefile=newFile(fileName);
try{
FileInputStreamfis=newFileInputStream(file);
ByteArrayOutputStreambos=newByteArrayOutputStream();
intlen=0;
while((len=fis.read())!=-1){
bos.write(len);
}
byte[]data=bos.toByteArray();
fis.close();
bos.close();
returndefineClass(name,data,0,data.length);
}catch(Exceptionex){
ex.printStackTrace();
}
returnsuper.findClass(name);
}
}
package com.chentaoqian.classloaderdemo;
import java.lang.reflect.Method;
public class ClassloaderTest {
public static void main(String[] args) {
MyClassloader2 myClassloader = new MyClassloader2("E:\\Test.class");
try {
//加載class文件
Class> c = myClassloader.loadClass("com.chentaoqian.test.Test");
if(c != null){
try {
Object obj = c.newInstance();
// Method method = c.getDeclaredMethod("sayHi", null);
Method method = c.getMethod("sayHi", null);
//通過反射調用Test類的say方法
method.invoke(obj, null);
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
packagecom.chentaoqian.classloaderdemo;
importjava.lang.reflect.Method;
publicclassClassloaderTest{
publicstaticvoidmain(String[]args){
MyClassloader2myClassloader=newMyClassloader2("E:\\Test.class");
try{
//加載class文件
Class>c=myClassloader.loadClass("com.chentaoqian.test.Test");
if(c!=null){
try{
Objectobj=c.newInstance();
//????????????????????Method method = c.getDeclaredMethod("sayHi", null);
Methodmethod=c.getMethod("sayHi",null);
//通過反射調用Test類的say方法
method.invoke(obj,null);
}catch(Exceptione){
e.printStackTrace();
}
}
}catch(ClassNotFoundExceptione){
e.printStackTrace();
}
}
}
這種方式可以正確加載class文件。需要注意的是:若該class文件使用了extends,則加載會報錯,因為父類找不到。
總結
以上是生活随笔為你收集整理的java 运行 加载jar,java运行时加载额外的 jar 包或 class的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 月圆之夜女巫最强卡组是什么
- 下一篇: 循环码差错图样matlab,基于MATL