小编给大家分享一下Java中自定义类加载器和动态加载的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
我们需要一个自定义的类加载器,完成任何路径包括网络的文件加载,这个是取得 java 字节码文件,也就是编译后的 class 文件,他可能在世界的某个角落。
实现自定义的类加载器首先是继承ClassLoader
这个类,来看下构造方法代码
public class MyClassLoad extends ClassLoader { private String rootPath; public MyClassLoad(String rootPath) { this.rootPath = rootPath; } }
构造方法,仅仅是把路径传入,也就是 class 文件的文件夹,不包括包名称的路径;
接下来重写findClass
方法;
/** * 根据name来寻找该类 * */ @Override protected Class<?> findClass(String name) throws ClassNotFoundException { Class<?> c = findLoadedClass(name); if (c == null) { // 内存堆中还没加载该类 c = findMyClass(name); // 自己实现加载类 } return c; }
首先在内存堆里面查找,没有加载的话就到自己实现,看下findMyClass
方法
/** * 加载该类 * * @param name * @return */ private Class<?> findMyClass(String name) { try { byte[] bytes = getData(name); return this.defineClass(null, bytes, 0, bytes.length); // 调用父类方法,生成具体类 } catch (Exception e) { e.printStackTrace(); } return null; }
该方法根据字节数组返回Class
类,根据 class 文件获取字节数组可以使用Apache 文件操作相关辅助类,这里使用原生 jdk 实现;
private byte[] getData(String className) { String path = rootPath + File.separatorChar + className.replace('.', File.separatorChar) + ".class"; InputStream is = null; try { is = new FileInputStream(path); ByteArrayOutputStream stream = new ByteArrayOutputStream(); byte[] buffer = new byte[2048]; int num = 0; while ((num = is.read(buffer)) != -1) { stream.write(buffer, 0, num); } return stream.toByteArray(); } catch (IOException e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; }
这个简单的自定义类加载器就差不多了,如果需要实现自己加密解密的可以在字节数组里面进行折腾,这里不再深入,我们的目标是热加载一段 java代码,可能的解决方法是,构建一个 java 模板,里面内置一些方法,外界可以增加一些新的方法,也可以调用内置方法。
好!开始一个简单的,把一段代码加载到内存并且执行吧。
import java.io.File;import java.io.FileWriter;import javax.tools.JavaCompiler;import javax.tools.JavaCompiler.CompilationTask;import classload.MyClassLoad;import javax.tools.JavaFileObject;import javax.tools.StandardJavaFileManager;import javax.tools.ToolProvider;public class LoadJava { public static final String javaCode = "package classload;public class HelloWorld2 {public HelloWorld2() {System.out.println(\"Hello World\");}}"; public static void runJavaCode() throws Exception { // 把 java String 存储到文件 String fileName = "/Users/XXXXXXX/Documents/demo/java/classload/HelloWorld2.java"; File file = new File(fileName); FileWriter fw = new FileWriter(file); fw.write(javaCode); fw.flush(); fw.close(); // JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager standardFileManager = javaCompiler.getStandardFileManager(null, null, null); Iterable<? extends JavaFileObject> iterable = standardFileManager.getJavaFileObjects(fileName); // 执行编译任务 CompilationTask task = javaCompiler.getTask(null, standardFileManager, null, null, null, iterable); task.call(); standardFileManager.close(); // 把编译后的 class 文件加载到内存 ClassLoader pcl = new MyClassLoad("/Users/XXXXXXX/Documents/demo/java/"); Class c = pcl.loadClass("classload.HelloWorld2"); System.out.println(c.newInstance()); } public static void main(String[] args) { try { LoadJava.runJavaCode(); } catch (Exception e) { e.printStackTrace(); } } }
以上是“Java中自定义类加载器和动态加载的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。