性能问答>类加载问题>
2回复

类加载问题



类加载问题
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会得到不一样的结果

2799 阅读
请先登录,查看2条精彩评论吧
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步