java 动态编译.java文件,然后动态加载运行

本文大部分代码,摘自Tomcat6.0源码。

提取Tomcat6.0动态编译java文件核心代码,修整而成。为以后的学习工作带来便利。

编译部分由JDT负责

由URLClassLoader动态加载.class文件后

通过java反射机制运行类

java 动态编译.java文件,然后动态加载运行_第1张图片

main.java

package com.dynamic; import java.io.File; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.Arrays; import com.dynamic.compile.DCompile; public class Main { private static String java_file_path = "D:/MyEclipse/DynamicCompile/com/compile/Test.java"; private static String java_basic_path = "D:/MyEclipse/DynamicCompile"; private static String ecode = "utf8"; public void execute() throws Exception{ DCompile dc = new DCompile(); dc.initialize(java_file_path, java_basic_path, ecode); Class clazz = dc.compile(); Object obj = clazz.newInstance(); Method method = clazz.getMethod("getName", new Class[]{String.class}); String name = (String)method.invoke(obj, "dbdxj"); System.out.println(name); } public static void main(String[] args) { Main m = new Main(); try{ m.execute(); }catch(Exception e){ e.printStackTrace(); } } } 

DCompilationUnit.java

package com.dynamic.compile; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.util.StringTokenizer; import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; public class DCompilationUnit implements ICompilationUnit { String className; String sourceFile; String javaEncoding; DCompilationUnit(String sourceFile, String className, String javaEncoding) { this.className = className; this.sourceFile = sourceFile; this.javaEncoding = javaEncoding; } public char[] getFileName() { return sourceFile.toCharArray(); } public char[] getContents() { char[] result = null; FileInputStream is = null; try { is = new FileInputStream(sourceFile); Reader reader = new BufferedReader(new InputStreamReader(is, javaEncoding)); if (reader != null) { char[] chars = new char[8192]; StringBuffer buf = new StringBuffer(); int count; while ((count = reader.read(chars, 0, chars.length)) > 0) { buf.append(chars, 0, count); } result = new char[buf.length()]; buf.getChars(0, result.length, result, 0); } } catch (IOException e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (IOException exc) { // Ignore } } } return result; } public char[] getMainTypeName() { int dot = className.lastIndexOf('.'); if (dot > 0) { return className.substring(dot + 1).toCharArray(); } return className.toCharArray(); } public char[][] getPackageName() { StringTokenizer izer = new StringTokenizer(className, "."); char[][] result = new char[izer.countTokens()-1][]; for (int i = 0; i < result.length; i++) { String tok = izer.nextToken(); result[i] = tok.toCharArray(); } return result; } }

DCompile.java

package com.dynamic.compile; import java.io.File; import java.net.URL; import java.net.URLClassLoader; import java.util.Locale; import java.util.Map; import java.util.HashMap; import org.eclipse.jdt.internal.compiler.Compiler; import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies; import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy; import org.eclipse.jdt.internal.compiler.IProblemFactory; import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; public class DCompile { private String java_file_path; private String java_basic_path; private String ecode; private Boolean init = false; private ICompilationUnit[] compilationUnits = null; public Class compile() throws Exception { if (!check()) { throw new Exception("Not initialize..."); } Class clazz = null; String targetClassName = getTargetClassName(); final DNameEnvironment env = new DNameEnvironment(targetClassName, java_file_path, Thread.currentThread().getContextClassLoader(), ecode); final IErrorHandlingPolicy policy = DefaultErrorHandlingPolicies .proceedWithAllProblems(); final DCompilerRequestor requestor = new DCompilerRequestor( java_basic_path); final IProblemFactory problemFactory = new DefaultProblemFactory(Locale .getDefault()); Compiler compiler = new Compiler(env, policy, getSettings(), requestor, problemFactory, true); compiler.compile(compilationUnits); URL url = new URL("file:/" + java_basic_path + "/"); System.out.println(url); URLClassLoader ucl = new URLClassLoader(new URL[]{url}); clazz = ucl.loadClass(targetClassName); return clazz; } public Map getSettings() { Map settings = new HashMap(); settings.put(CompilerOptions.OPTION_LineNumberAttribute, CompilerOptions.GENERATE); settings.put(CompilerOptions.OPTION_SourceFileAttribute, CompilerOptions.GENERATE); settings.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE); settings.put(CompilerOptions.OPTION_Encoding, ecode); // Source JVM settings .put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_6); // Target JVM settings.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6); settings.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_6); return settings; } private boolean check() { return init; } public DCompile() { } public String getTargetClassName() { String targetClassName = java_file_path.substring(java_basic_path .length() + 1, java_file_path.indexOf(".")); return targetClassName.replace("/", "."); } public void initialize(String file_path, String basic_path, String ecode) { this.java_file_path = file_path; this.java_basic_path = basic_path; this.ecode = ecode; String targetClassName = getTargetClassName(); if (targetClassName == null) { targetClassName = ""; } compilationUnits = new ICompilationUnit[1]; compilationUnits[0] = new DCompilationUnit(this.java_file_path, targetClassName, this.ecode); init = true; } }

DCompilerRequestor.java

package com.dynamic.compile; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.internal.compiler.ClassFile; import org.eclipse.jdt.internal.compiler.CompilationResult; import org.eclipse.jdt.internal.compiler.ICompilerRequestor; public class DCompilerRequestor implements ICompilerRequestor{ private String outputDir; public DCompilerRequestor(String outDir){ this.outputDir = outDir; } public void acceptResult(CompilationResult result) { try { boolean error = false; if (result.hasProblems()) { IProblem[] problems = result.getProblems(); for (int i = 0; i < problems.length; i++) { IProblem problem = problems[i]; if (problem.isError()) { error = true; System.err.println(problem.toString()); } } } if (!error) { ClassFile[] classFiles = result.getClassFiles(); for (int i = 0; i < classFiles.length; i++) { ClassFile classFile = classFiles[i]; char[][] compoundName = classFile.getCompoundName(); String className = ""; String sep = ""; for (int j = 0; j < compoundName.length; j++) { className += sep; className += new String(compoundName[j]); sep = "."; } byte[] bytes = classFile.getBytes(); String outFile = outputDir + "/" + className.replace('.', '/') + ".class"; FileOutputStream fout = new FileOutputStream(outFile); BufferedOutputStream bos = new BufferedOutputStream(fout); bos.write(bytes); bos.close(); } } } catch (IOException exc) { exc.printStackTrace(); } } }

DNameEnvironment.java

package com.dynamic.compile; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; import org.eclipse.jdt.internal.compiler.env.INameEnvironment; import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; public class DNameEnvironment implements INameEnvironment { private String targetClassName; private String sourceFile; private ClassLoader classLoader; private String encode; public DNameEnvironment(String targetClassName, String sourceFile, ClassLoader classLoader, String encode){ this.targetClassName = targetClassName; this.sourceFile = sourceFile; this.classLoader = classLoader; this.encode = encode; } public NameEnvironmentAnswer findType(char[][] compoundTypeName) { String result = ""; String sep = ""; for (int i = 0; i < compoundTypeName.length; i++) { result += sep; result += new String(compoundTypeName[i]); sep = "."; } return findType(result); } public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) { String result = ""; String sep = ""; for (int i = 0; i < packageName.length; i++) { result += sep; result += new String(packageName[i]); sep = "."; } result += sep; result += new String(typeName); return findType(result); } private NameEnvironmentAnswer findType(String className) { InputStream is = null; try { if (className.equals(targetClassName)) { ICompilationUnit compilationUnit = new DCompilationUnit( sourceFile, className, encode); return new NameEnvironmentAnswer(compilationUnit, null); } String resourceName = className.replace('.', '/') + ".class"; is = classLoader.getResourceAsStream(resourceName); if (is != null) { byte[] classBytes; byte[] buf = new byte[8192]; ByteArrayOutputStream baos = new ByteArrayOutputStream( buf.length); int count; while ((count = is.read(buf, 0, buf.length)) > 0) { baos.write(buf, 0, count); } baos.flush(); classBytes = baos.toByteArray(); char[] fileName = className.toCharArray(); ClassFileReader classFileReader = new ClassFileReader( classBytes, fileName, true); return new NameEnvironmentAnswer(classFileReader, null); } } catch (IOException exc) { exc.printStackTrace(); } catch (org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException exc) { exc.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (IOException exc) { // Ignore } } } return null; } private boolean isPackage(String result) { if (result.equals(targetClassName)) { return false; } String resourceName = result.replace('.', '/') + ".class"; InputStream is = classLoader.getResourceAsStream(resourceName); return is == null; } public boolean isPackage(char[][] parentPackageName, char[] packageName) { String result = ""; String sep = ""; if (parentPackageName != null) { for (int i = 0; i < parentPackageName.length; i++) { result += sep; String str = new String(parentPackageName[i]); result += str; sep = "."; } } String str = new String(packageName); if (Character.isUpperCase(str.charAt(0))) { if (!isPackage(result)) { return false; } } result += sep; result += str; return isPackage(result); } public void cleanup() { } }

Test.java

package com.compile; public class Test{ public Test(){ System.out.println("initialize... Test.class"); } public String getName(String name){ return ("孙子你成功了:" + name); } }

动态编译后.class文件自动生成

java 动态编译.java文件,然后动态加载运行_第2张图片

WindowsXP  JDK6 测试通过

Console:

file:/D:/MyEclipse/DynamicCompile/
initialize... Test.class
孙子你成功了:dbdxj

 

 

这只是简单的提取,详细的学习待续。。。


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

最新文件 更新时间:2010,04,15

更新内容包括引用外部文件,引用外部jar包,引用当前程序文件等。

http://download.csdn.net/source/2244811

你可能感兴趣的:(J2SE,J2EE,Tomcat)