今天在弄游戏的GM模块,大部分gm命令很简单,只是单纯改变某些参数的值。
突然,想到一个问题,就是在线上运行服务器时,假如我要改变某个参数的值,有
没有办法呢?通过查找资料后,发现jdk竟然也提供了动态编译的工具。因此,我
们可以让java变成一个脚本语言。我发送一个类的代码到服务端,动态编译后,利
用反射来执行。代码很简单,我从网上找了一个例子简单改装一下
import java.io.IOException; import java.lang.reflect.Method; import java.net.URI; import java.net.URL; import java.net.URLClassLoader; import java.util.Arrays; import java.util.Scanner; import javax.tools.JavaCompiler; import javax.tools.JavaCompiler.CompilationTask; import javax.tools.JavaFileObject; import javax.tools.SimpleJavaFileObject; import javax.tools.ToolProvider; public class CompileTest { public static final String CLASS_CONTENT = "public class HelloWorld{public static void run(){##;}}"; public static void main(String[] args) throws Exception { Scanner scanner =new Scanner(System.in); String code = scanner.nextLine(); code = CLASS_CONTENT.replace("##", code); //获取编译器.注意,运行时需要jdk,单纯的jre没有编译器 JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); JavaFileObject fileObject = new JavaStringObject("HelloWorld", code); //编译过程 CompilationTask task = javaCompiler.getTask(null, null, null, Arrays.asList("-d", "./bin"), null, Arrays.asList(fileObject)); if (!task.call()) { System.out.println("编译失败!"); } else { System.out.println("编译成功!"); //成功以后,就利用发射来执行这个类了 URL[] urls = new URL[] { new URL("file:/" + "./bin/") }; URLClassLoader classLoader = new URLClassLoader(urls); Class<?> clazz = classLoader.loadClass("HelloWorld"); Method method = clazz.getDeclaredMethod("run"); method.invoke(clazz.newInstance()); } } static class JavaStringObject extends SimpleJavaFileObject { private String code; public JavaStringObject(String name, String code) { super(URI.create(name + ".java"), Kind.SOURCE); this.code = code; } @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { return code; } } }
运行代码
输入一条java语句,例如:System.out.println("hello,美女!");
总结
利用java的这个小特性,我们可以做一些有益的事情,很多时候不需要为了更改某些参数而停服了。
参考资料
http://www.cnblogs.com/flyoung2008/