Java Compiler API with classes that depend on each other
我正在使用Java Compiler API编译内存中的类。也就是说,将类编译为字节码(没有.classes文件存储在磁盘中),然后通过重构字节码来加载。
有时,我需要编译一个依赖于另一个(也是在内存中编译的)类的类。例如:编译A类,然后编译依赖于A类的B类。
为解决此问题,我同时将A类和B类作为编译器API的getTask方法所需的编译单元。
但是,我真的不喜欢这种解决方案,因为它使我重新编译了已经编译的ClassA。
有没有办法解决这个问题?
编辑:我通过此链接找到了一种解决方案:http://www.ibm.com/developerworks/java/library/j-jcomp/index.html
是的,只要正确实现了
1 2 3 4 5 6 7 8 9 | @Override public String inferBinaryName(Location location, JavaFileObject javaFileObject) { if(location == StandardLocation.CLASS_PATH && javaFileObject instanceof InAppJavaFileObject) { return StringUtils.substringBeforeLast(javaFileObject.getName(),".java"); } return super.inferBinaryName(location, javaFileObject); } |
请注意,我将从结尾处剥离" .java"。构造
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 | @Override public Iterable<JavaFileObject> list(Location action, String pkg, Set<JavaFileObject.Kind> kind, boolean recurse) throws IOException { Iterable<JavaFileObject> superFiles = super.list(action, pkg, kind, recurse); // see if there's anything in our cache that matches the criteria. if(action == StandardLocation.CLASS_PATH && (kind.contains(JavaFileObject.Kind.CLASS) || kind.contains(JavaFileObject.Kind.SOURCE))) { List<JavaFileObject> ourFiles = new ArrayList<JavaFileObject>(); for(Map.Entry<String,InAppJavaFileObject> entry : files.entrySet()) { String className = entry.getKey(); if(className.startsWith(pkg) && ("".equals(pkg) || pkg.equals(className.substring(0, className.lastIndexOf('.'))))) { ourFiles.add(entry.getValue()); } } if(ourFiles.size() > 0) { for(JavaFileObject javaFileObject : superFiles) { ourFiles.add(javaFileObject); } return ourFiles; } } // nothing found in our hash map that matches the criteria... return // whatever super came up with. return superFiles; } |
一旦正确实现了这些方法,其余方法就可以正常工作。尽情享受吧!
这引出了一个显而易见的问题,即为什么要首先单独编译A类。为什么不一口气编译所有内容?
我认为您不能避免同时编译这两个类。实际上,如果您不同时编译它们两者,则最终可能会遇到二进制兼容性问题或内联常数不正确的问题。
与从命令行编译一个类而不编译另一个类时遇到的问题本质上是相同的。
但是,老实说,我不会担心尝试像这样优化编译。 (并且,如果您的应用程序需要能够动态编译一个类而不是另一个,则可能存在重大的设计问题。)
如何保持文件的修改时间和(内存中的)已编译字节码?