ToolProvider.getSystemJavaCompiler() return null 的解决方法

【1】利用java 编译器API 编译 普通的java文件

1.1)代码如下:

package com.corejava.chapter10_2;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;

public class JavaCompilerTest
{
	public static void main(String[] args) throws FileNotFoundException
	{
		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
		OutputStream out = new FileOutputStream("out.txt");
		OutputStream err = new FileOutputStream("err.txt");
		System.out.println(compiler);
		System.out.println(System.getProperty("java.home"));
		int result = compiler.run(null, out, err, "com/corejava/chapter10_2/Hello.java");
		if(result == 0)
		{
			System.out.println("bingo");
		}
		else
		{
			System.out.println("oops");
		}
	}
}
1.2)错误如下(null 指针异常):


-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

【2】 解决方法

2.1)通过  System.out.println(System.getProperty("java.home")); ,我们知道了 java.home ==  C:\Program Files\Java\jre1.8.0_60 ; 

引用 http://www.cnblogs.com/fangwenyu/archive/2011/10/12/2209051.html  中的解决方法,通过查看 ToolProvider 的源代码,我们知道 他需要查找 java.home 下面的 lib 里的 tools.jar 文件, 而 tools.jar 文件通常在 jdk/lib 文件夹而没有在 jre中, 所以,我们只需要把 tools.jar 复制到 你的java.home映射目录/lib/ 就可以了;

2.2)复制 tools.jar 到 C:\Program Files\Java\jre1.8.0_60\lib(java.home == C:\Program Files\Java\jre1.8.0_60\)中后,运行结果为:



【3】 Conclusion

C1)需要知道 jvm 中的 java.home 映射的目录是什么? 不要瞎copy;

C2)知道 java.home后,就将 tool.jar copy 到 其路径下面 的 lib 文件夹中;


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要获取完整的Java方法体字符串,可以使用Java编译器API或第三方库来实现。以下是使用Java编译器API的示例代码: ```java import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; import java.io.IOException; import java.io.StringWriter; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class MethodBodyToString { public static String getMethodBodyAsString(Class<?> clazz, String methodName, Class<?>... parameterTypes) throws IOException { // 获取方法的源代码 String methodSource = getMethodSource(clazz, methodName, parameterTypes); // 将源代码写入临时文件 Path tempFile = Files.createTempFile("MethodBodyToString", ".java"); Files.write(tempFile, methodSource.getBytes(StandardCharsets.UTF_8)); // 编译临时文件并获取类文件 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(tempFile.toFile()); StringWriter writer = new StringWriter(); JavaCompiler.CompilationTask task = compiler.getTask(writer, fileManager, null, null, null, compilationUnits); boolean success = task.call(); if (!success) { throw new RuntimeException("Compilation failed"); } byte[] classBytes = Files.readAllBytes(Paths.get(clazz.getResource(clazz.getSimpleName() + ".class").getPath())); // 使用ASM库解析类文件并获取方法体 ClassNode classNode = new ClassNode(); ClassReader classReader = new ClassReader(classBytes); classReader.accept(classNode, 0); MethodNode methodNode = null; for (MethodNode node : classNode.methods) { if (node.name.equals(methodName) && Arrays.equals(getParameterTypes(node), parameterTypes)) { methodNode = node; break; } } if (methodNode == null) { throw new NoSuchMethodException("Method not found: " + clazz.getName() + "." + methodName); } // 使用Textifier类将方法体转换为字符串 StringWriter methodWriter = new StringWriter(); TraceMethodVisitor methodVisitor = new TraceMethodVisitor(null, new Textifier(), methodWriter); methodNode.accept(methodVisitor); return methodWriter.toString(); } private static String getMethodSource(Class<?> clazz, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException, IOException { Method method = clazz.getMethod(methodName, parameterTypes); String className = clazz.getSimpleName(); String methodNameWithParams = method.getName() + "(" + getParameterTypeNames(method.getParameterTypes()) + ")"; String methodBody = method.toString().substring(method.toString().indexOf("{")); return "public class " + className + " {\n" + " public static " + method.getReturnType().getSimpleName() + " " + methodNameWithParams + methodBody + "\n" + "}"; } private static String getParameterTypeNames(Class<?>[] parameterTypes) { return Arrays.stream(parameterTypes).map(Class::getSimpleName).collect(Collectors.joining(", ")); } private static Class<?>[] getParameterTypes(MethodNode methodNode) { Type[] argumentTypes = Type.getArgumentTypes(methodNode.desc); Class<?>[] parameterTypes = new Class<?>[argumentTypes.length]; for (int i = 0; i < argumentTypes.length; i++) { parameterTypes[i] = toClass(argumentTypes[i]); } return parameterTypes; } private static Class<?> toClass(Type type) { switch (type.getSort()) { case Type.BOOLEAN: return boolean.class; case Type.BYTE: return byte.class; case Type.CHAR: return char.class; case Type.SHORT: return short.class; case Type.INT: return int.class; case Type.LONG: return long.class; case Type.FLOAT: return float.class; case Type.DOUBLE: return double.class; case Type.ARRAY: return Array.newInstance(toClass(type.getElementType()), 0).getClass(); case Type.OBJECT: try { return Class.forName(type.getClassName()); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } default: throw new IllegalArgumentException("Unsupported type: " + type); } } } ``` 该方法先获取Java方法的源代码,然后将源代码写入临时文件,编译临时文件并获取类文件,最后使用ASM库解析类文件并获取方法体。注意需要将ASM库添加到项目中。你可以在方法体中修改具体的类名、方法名和参数类型来获取不同的方法体。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值