java compiler类_Java JavaCompiler.run()也可以编译匿名类

小编典典

显然,您loadStrategyClass是在custom中定义的ClassLoader。问题在于,defineClass对于感兴趣的类仅调用一次是不够的,您的类加载器通常必须通过实现才能按需解析类findClass,以便JVM可以解析依赖项,例如内部类。

您没有指定如何获取方法的strategyClassFile参数loadStrategyClass。由于您没有任何选择地运行编译器,因此我想您只是相对于源文件查找了文件。要解决其他依赖关系,需要知道类目录的实际根目录。当您定义存储类文件的位置时,它将变得更加容易,例如

// customize these, if you want, null triggers default behavior

DiagnosticListener diagnosticListener = null;

Locale locale = null;

JavaCompiler c = ToolProvider.getSystemJavaCompiler();

StandardJavaFileManager fm

= c.getStandardFileManager(diagnosticListener, locale, Charset.defaultCharset());

// define where to store compiled class files - use a temporary directory

Path binaryDirectory = Files.createTempDirectory("compile-test");

fm.setLocation(StandardLocation.CLASS_OUTPUT,

Collections.singleton(binaryDirectory.toFile()));

JavaCompiler.CompilationTask task = c.getTask(null, fm,

diagnosticListener, Collections.emptySet(), Collections.emptySet(),

// to make this a stand-alone example, I use embedded source code

Collections.singleton(new SimpleJavaFileObject(

URI.create("string:///Class1.java"), Kind.SOURCE) {

public CharSequence getCharContent(boolean ignoreEncodingErrors) {

return "package test;\npublic class Class1 { public class Inner {} }";

}

}));

if(task.call()) try {

URLClassLoader cl = new URLClassLoader(new URL[]{ binaryDirectory.toUri().toURL() });

Class> loadedClass = cl.loadClass("test.Class1");

System.out.println("loaded "+loadedClass);

System.out.println("inner classes: "+Arrays.toString(loadedClass.getClasses()));

} catch(ClassNotFoundException ex) {

ex.printStackTrace();

}

在上面的示例中,我们知道了类目录的根,因为已经定义了它。这允许简单地使用现有的URLClassLoader而不是实现新型的类加载器。当然,使用自定义文件管理器,我们还可以将内存存储用于临时目录。

您可以使用此API来发现生成的内容,这使您可以使用生成的类而无需事先知道要编译的源文件中存在哪些包或内部类声明。

public static Class> compile(

DiagnosticListener diagnosticListener,

Locale locale, String sourceFile) throws IOException, ClassNotFoundException {

JavaCompiler c = ToolProvider.getSystemJavaCompiler();

StandardJavaFileManager fm

= c.getStandardFileManager(diagnosticListener, locale, Charset.defaultCharset());

// define where to store compiled class files - use a temporary directory

Path binaryDirectory = Files.createTempDirectory("compile-test");

fm.setLocation(StandardLocation.CLASS_OUTPUT,

Collections.singleton(binaryDirectory.toFile()));

JavaCompiler.CompilationTask task = c.getTask(null, fm,

diagnosticListener, Collections.emptySet(), Collections.emptySet(),

fm.getJavaFileObjects(new File(sourceFile)));

if(task.call()) {

Class> clazz = null;

URLClassLoader cl = new URLClassLoader(new URL[]{binaryDirectory.toUri().toURL()});

for(JavaFileObject o: fm.list(

StandardLocation.CLASS_OUTPUT, "", Collections.singleton(Kind.CLASS), true)) {

String s = binaryDirectory.toUri().relativize(o.toUri()).toString();

s = s.substring(0, s.length()-6).replace('/', '.');

clazz = cl.loadClass(s);

while(clazz.getDeclaringClass() != null) clazz = clazz.getDeclaringClass();

if(Modifier.isPublic(clazz.getModifiers())) break;

}

if(clazz != null) return clazz;

throw new ClassNotFoundException(null,

new NoSuchElementException("no top level class generated"));

}

throw new ClassNotFoundException(null,

new NoSuchElementException("compilation failed"));

}

如果使用此方法动态绑定插件或模块,则可以扩展搜索以查找实现特定接口或具有特定批注的结果类。

2020-11-23

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值