2回复
3年前
类加载问题
类加载问题
JavassistCompiler.java
package com.lli.classloader.javassist;
import javassist.*;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
/**
* @Description
* @Author langli
* @Date 2021-02-08 11:20
*/
public class JavassistCompiler {
/**
* Javassist的类池
*/
private ClassPool classPool;
private URL[] classPathUrls;
public JavassistCompiler() {
this.classPool = new ClassPool();
this.classPool.appendSystemPath();
this.classPool.insertClassPath(new ClassClassPath(this.getClass()));
this.classPathUrls = getClassPathUrls();
}
public Class<?> compile(SourceCode sourceCode) {
StringBuilder className = new StringBuilder(sourceCode.getClassName());
CtClass byteCodeClass = classPool.makeClass(className.toString());
Class<?> compiledClass = null;
try {
CtClass abstractMapperClass = classPool.get(sourceCode.getSuperClass().getCanonicalName());
// 1 byteCodeClass.setSuperclass(abstractMapperClass);
compiledClass = byteCodeClass.toClass(buildClassPathClassLoader(),
this.getClass().getProtectionDomain());
} catch (CannotCompileException e) {
e.printStackTrace();
} catch (NotFoundException e) {
e.printStackTrace();
}
return compiledClass;
}
private ClassLoader buildClassPathClassLoader() {
return new URLClassLoader(this.classPathUrls, Thread.currentThread().getContextClassLoader());
// 2 return new URLClassLoader(this.classPathUrls);
}
private URL[] getClassPathUrls() {
List<URL> urlList = new ArrayList<URL>();
List<String> classPathList = new ArrayList<String>();
Enumeration<URL> resources = null;
try {
resources = getClass().getClassLoader().getResources("");
} catch (IOException e) {
e.printStackTrace();
}
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
String path = url.getPath();
if (path.contains(".jar")) {
urlList.add(url);
}
}
String classesPath = getClass().getClassLoader().getResource("").getPath();
classPathList.add(classesPath);
try {
urlList.add(new File(classesPath).toURI().toURL());
} catch (MalformedURLException e) {
e.printStackTrace();
}
URL[] urls = new URL[urlList.size()];
return urlList.toArray(urls);
}
}
SourceCode.java
package com.lli.classloader.javassist;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @Description
* @Author langli
* @Date 2021-02-08 10:12
*/
public class SourceCode {
private String packageName;
private Class superClass;
private StringBuilder sourceBuilder;
private String classSimpleName;
private String className;
/**
* 源代码的方法
*/
private List<String> methods;
/**
* 源代码的变量
*/
private List<String> fields;
private static final AtomicInteger UNIQUE_CLASS_INDEX = new AtomicInteger();
public static final char LF = '\n';
public SourceCode(final String baseClassName, Class superClass) {
this.sourceBuilder = new StringBuilder();
this.superClass = superClass;
this.classSimpleName = getUniqueClassName(baseClassName);
this.packageName = "com.lli.test";
this.className = this.packageName + "." + this.classSimpleName;
sourceBuilder.append("package ");
sourceBuilder.append(packageName);
sourceBuilder.append(LF);
sourceBuilder.append(LF);
sourceBuilder.append("public class ");
sourceBuilder.append(this.classSimpleName);
sourceBuilder.append(" extends A {");
}
private String getUniqueClassName(String name) {
return name + System.nanoTime() + "$" + UNIQUE_CLASS_INDEX.getAndIncrement();
}
public String toSourceFile() {
return sourceBuilder.toString() + LF + "}";
}
public String getPackageName() {
return packageName;
}
public Class getSuperClass() {
return superClass;
}
public StringBuilder getSourceBuilder() {
return sourceBuilder;
}
public String getClassSimpleName() {
return classSimpleName;
}
public String getClassName() {
return className;
}
public List<String> getMethods() {
return methods;
}
public List<String> getFields() {
return fields;
}
}
package com.lli.classloader.javassist;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @Description
* @Author langli
* @Date 2021-02-08 10:12
*/
public class SourceCode {
private String packageName;
private Class superClass;
private StringBuilder sourceBuilder;
private String classSimpleName;
private String className;
/**
* 源代码的方法
*/
private List<String> methods;
/**
* 源代码的变量
*/
private List<String> fields;
private static final AtomicInteger UNIQUE_CLASS_INDEX = new AtomicInteger();
public static final char LF = '\n';
public SourceCode(final String baseClassName, Class superClass) {
this.sourceBuilder = new StringBuilder();
this.superClass = superClass;
this.classSimpleName = getUniqueClassName(baseClassName);
this.packageName = "com.lli.test";
this.className = this.packageName + "." + this.classSimpleName;
sourceBuilder.append("package ");
sourceBuilder.append(packageName);
sourceBuilder.append(LF);
sourceBuilder.append(LF);
sourceBuilder.append("public class ");
sourceBuilder.append(this.classSimpleName);
sourceBuilder.append(" extends A {");
}
private String getUniqueClassName(String name) {
return name + System.nanoTime() + "$" + UNIQUE_CLASS_INDEX.getAndIncrement();
}
public String toSourceFile() {
return sourceBuilder.toString() + LF + "}";
}
public String getPackageName() {
return packageName;
}
public Class getSuperClass() {
return superClass;
}
public StringBuilder getSourceBuilder() {
return sourceBuilder;
}
public String getClassSimpleName() {
return classSimpleName;
}
public String getClassName() {
return className;
}
public List<String> getMethods() {
return methods;
}
public List<String> getFields() {
return fields;
}
}
A.java
package com.lli.test;
/**
* @Description
* @Author langli
* @Date 2021-02-08 11:26
*/
public class A {
}
JavassistCompilerTest.java
package com.lli.classloader.javassist;
import com.lli.test.A;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.junit.Assert.*;
// 3 @RunWith(PowerMockRunner.class)
public class JavassistCompilerTest {
@Test
public void test() {
SourceCode sourceCode = new SourceCode("B", A.class);
JavassistCompiler javassistCompiler = new JavassistCompiler();
Class<?> compiledClass = javassistCompiler.compile(sourceCode);
System.out.println(compiledClass.getClassLoader());
try {
A a = (A) compiledClass.newInstance();
System.out.println(a.getClass().getClassLoader());
System.out.println(A.class.getClassLoader());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
代码中加注释的三个地方,打开关闭,运行test会得到不一样的结果
3139 阅读