您当前的位置: 首页 >  Java

qq_34412985

暂无认证

  • 0浏览

    0关注

    1061博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

java解决动态编译加载不到import的jar包

qq_34412985 发布时间:2021-01-31 15:51:21 ,浏览量:0

package com.*.utils;

import java.net.URL; import java.net.URLClassLoader; import java.util.Arrays; import java.util.HashMap; import java.util.Map;

import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider;

public class DynamicLoader {

    /**      * 通过类名和其代码(Java代码字符串),编译得到字节码,返回类名及其对应类的字节码,封装于Map中,值得注意的是,      * 平常类中就编译出来的字节码只有一个类,但是考虑到内部类的情况, 会出现很多个类名及其字节码,所以用Map封装方便。      *      * @param javaName 类名      * @param javaSrc  Java源码      * @return map      */     public static Map compile(String javaName, String javaSrc) throws Exception {         Map map = new HashMap();         // 调用java编译器接口         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();         StandardJavaFileManager stdManager = compiler.getStandardFileManager(null, null, null);

        URL[] s = ((URLClassLoader) DynamicLoader.class.getClassLoader()).getURLs();         URLClassLoader loader = new URLClassLoader(s, Thread.currentThread().getContextClassLoader());         MemoryJavaFileManager manager = new MemoryJavaFileManager(loader, stdManager);         JavaFileObject javaFileObject = MemoryJavaFileManager.makeStringSource(javaName, javaSrc);

        JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, null, null,                 Arrays.asList(javaFileObject));

        boolean status = task.call();         map.put("status", status);         if (status) {             map.put("byte", manager.getClassBytes());         }         return map;     }

    /**      * 先根据类名在内存中查找是否已存在该类,若不存在则调用 URLClassLoader的 defineClass方法加载该类      * URLClassLoader的具体作用就是将class文件加载到jvm虚拟机中去      *      * @author Administrator      *      */     public static class MemoryClassLoader extends ClassLoader {         // private static final String CLASS_LOADER_NAME = "MemoryClassLoader";         Map classBytes = new HashMap();

        public MemoryClassLoader(ClassLoader parent, Map classBytes) {             super(parent);             this.classBytes.putAll(classBytes);         }

        @Override         protected Class findClass(String name) throws ClassNotFoundException {             byte[] buf = classBytes.get(name);             if (buf == null) {                 return super.findClass(name);             }             classBytes.remove(name);             return defineClass(name, buf, 0, buf.length);         }     } }

package com.*.utils;

import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FilterOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.StringReader; import java.io.Writer; import java.net.JarURLConnection; import java.net.URI; import java.net.URL; import java.net.URLClassLoader; import java.nio.CharBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.jar.JarEntry;

import javax.lang.model.element.Modifier; import javax.lang.model.element.NestingKind; import javax.tools.FileObject; import javax.tools.ForwardingJavaFileManager; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.SimpleJavaFileObject; import javax.tools.StandardLocation;

/**  * 将编译好的.class文件保存到内存当中,这里的内存也就是map映射当中  */ @SuppressWarnings("rawtypes") public final class MemoryJavaFileManager extends ForwardingJavaFileManager {

    private final static String EXT = ".java";// Java源文件的扩展名     private Map classBytes;// 用于存放.class文件的内存     private URLClassLoader classLoader;

    @SuppressWarnings("unchecked")     public MemoryJavaFileManager(URLClassLoader classLoader, JavaFileManager fileManager) {         super(fileManager);         classBytes = new HashMap();         this.classLoader = classLoader;     }

    public Map getClassBytes() {         return classBytes;     }

    @Override     public void close() throws IOException {         classBytes = new HashMap();     }

    @Override     public void flush() throws IOException {     }

    @Override     public ClassLoader getClassLoader(Location location) {         return classLoader;     }

    @Override     public String inferBinaryName(Location location, JavaFileObject file) {         String ret = "";         if (file instanceof CustomJavaFileObject) {             ret = ((CustomJavaFileObject) file).binaryName;         } else {             ret = super.inferBinaryName(location, file);         }         return ret;     }

    @SuppressWarnings("unchecked")     @Override     public Iterable list(Location location, String packageName, Set kinds, boolean recurse)             throws IOException {         Iterable ret = null;         if (location == StandardLocation.PLATFORM_CLASS_PATH) {             ret = super.list(location, packageName, kinds, recurse);         } else if (location == StandardLocation.CLASS_PATH && kinds.contains(JavaFileObject.Kind.CLASS)) {             ret = find(packageName);             if (ret == null || (!ret.iterator().hasNext())) {                 ret = super.list(location, packageName, kinds, recurse);             }         } else {             ret = Collections.emptyList();         }         return ret;     }

    public static class CustomJavaFileObject implements JavaFileObject {         private String binaryName;         private URI uri;         private String name;

        public String binaryName() {             return binaryName;         }

        public CustomJavaFileObject(String binaryName, URI uri) {             this.uri = uri;             this.binaryName = binaryName;             name = uri.getPath() == null ? uri.getSchemeSpecificPart() : uri.getPath();         }

        @Override         public Kind getKind() {             return Kind.CLASS;         }

        @Override         public boolean isNameCompatible(String simpleName, Kind kind) {             String baseName = simpleName + kind.extension;             return kind.equals(getKind()) && (baseName.equals(getName()) || getName().endsWith("/" + baseName));         }

        @Override         public NestingKind getNestingKind() {             throw new UnsupportedOperationException();         }

        @Override         public Modifier getAccessLevel() {             throw new UnsupportedOperationException();         }

        @Override         public URI toUri() {             return uri;         }

        @Override         public String getName() {             return name;         }

        @Override         public InputStream openInputStream() throws IOException {             return uri.toURL().openStream();         }

        @Override         public OutputStream openOutputStream() throws IOException {             throw new UnsupportedOperationException();         }

        @Override         public Reader openReader(boolean ignoreEncodingErrors) throws IOException {             throw new UnsupportedOperationException();         }

        @Override         public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {             throw new UnsupportedOperationException();         }

        @Override         public Writer openWriter() throws IOException {             throw new UnsupportedOperationException();         }

        @Override         public long getLastModified() {             return 0;         }

        @Override         public boolean delete() {             throw new UnsupportedOperationException();         }     }

    private List find(String packageName) {         List result = new ArrayList();         String javaPackageName = packageName.replaceAll("\\.", "/");         try {             Enumeration urls = classLoader.findResources(javaPackageName);             while (urls.hasMoreElements()) {                 URL ll = urls.nextElement();                 String ext_form = ll.toExternalForm();                 if (ext_form.lastIndexOf("!") > 0) {                     String jar = ext_form.substring(0, ext_form.lastIndexOf("!"));                     String pkg = ext_form.substring(ext_form.lastIndexOf("!") + 1);

                    JarURLConnection conn = (JarURLConnection) ll.openConnection();                     conn.connect();                     Enumeration jar_items = conn.getJarFile().entries();                     while (jar_items.hasMoreElements()) {                         JarEntry item = jar_items.nextElement();                         if (item.isDirectory() || (!item.getName().endsWith(".class"))) {                             continue;                         }                         if (item.getName().lastIndexOf("/") != (pkg.length() - 1)) {                             continue;                         }                         String name = item.getName();                         URI uri = URI.create(jar + "!/" + name);                         String binaryName = name.replaceAll("/", ".");                         binaryName = binaryName.substring(0, binaryName.indexOf(JavaFileObject.Kind.CLASS.extension));                         result.add(new CustomJavaFileObject(binaryName, uri));                     }                 }             }         } catch (Exception e) {             e.printStackTrace();         }         return result;     }

    /**      * 一个文件对象,用来表示从string中获取到的source,一下类容是按照jkd给出的例子写的      */     private static class StringInputBuffer extends SimpleJavaFileObject {         // The source code of this "file".         final String code;

        /**          * Constructs a new JavaSourceFromString.          *          * @param name 此文件对象表示的编译单元的name          * @param code 此文件对象表示的编译单元source的code          */         StringInputBuffer(String name, String code) {             super(toURI(name), Kind.SOURCE);             this.code = code;         }

        @Override         public CharBuffer getCharContent(boolean ignoreEncodingErrors) {             return CharBuffer.wrap(code);         }

        @SuppressWarnings("unused")         public Reader openReader() {             return new StringReader(code);         }     }

    /**      * 将Java字节码存储到classBytes映射中的文件对象      */     private class ClassOutputBuffer extends SimpleJavaFileObject {         private String name;

        /**          * @param name className          */         ClassOutputBuffer(String name) {             super(toURI(name), Kind.CLASS);             this.name = name;         }

        @Override         public OutputStream openOutputStream() {             return new FilterOutputStream(new ByteArrayOutputStream()) {                 @Override                 public void close() throws IOException {                     out.close();                     ByteArrayOutputStream bos = (ByteArrayOutputStream) out;

                    // 这里需要修改                     classBytes.put(name, bos.toByteArray());                 }             };         }     }

    @Override     public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className,             JavaFileObject.Kind kind, FileObject sibling) throws IOException {         if (kind == JavaFileObject.Kind.CLASS) {             return new ClassOutputBuffer(className);         } else {             return super.getJavaFileForOutput(location, className, kind, sibling);         }     }

    static JavaFileObject makeStringSource(String name, String code) {         return new StringInputBuffer(name, code);     }

    static URI toURI(String name) {         File file = new File(name);         if (file.exists()) {// 如果文件存在,返回他的URI             return file.toURI();         } else {             try {                 final StringBuilder newUri = new StringBuilder();                 newUri.append("mfm:///");                 newUri.append(name.replace('.', '/'));                 if (name.endsWith(EXT)) {                     newUri.replace(newUri.length() - EXT.length(), newUri.length(), EXT);                 }                 return URI.create(newUri.toString());             } catch (Exception exp) {                 return URI.create("mfm:///com/sun/script/java/java_source");             }         }     } }

 

关注
打赏
1653291990
查看更多评论
立即登录/注册

微信扫码登录

0.0398s