java动态编译类文件并加载到内存中
如果你想在动态编译并加载了class后,能够用hibernate的数据访问接口以面向对象的方式来操作该class类,请参考这篇博文-http://www.cnblogs.com/anai/p/4270214.html
所谓动态编译,就是在程序运行时产生java类,并编译成class文件。
一、这里介绍两种动态编译java文件的方式。
第一种:使用Runtime执行javac命令
/** * 编译java类 * 使用Runtime执行javac命令 * @param name 类的全限定包名 不带后缀 例如com.test.Notice 而不要写成com.test.Notice.java * @throws java.io.IOException */ public static void javac(String name) throws IOException { String javaPackageName = name.replace(".",File.separator)+".java"; String javaAbsolutePath = classPath+javaPackageName; Process process = Runtime.getRuntime().exec("javac -classpath "+ jarAbsolutePath+ " " + javaAbsolutePath); try { InputStream errorStream = process.getErrorStream(); InputStreamReader inputStreamReader = new InputStreamReader(errorStream); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String line = null; while ((line=bufferedReader.readLine()) != null){ System.out.println(line); } int exitVal = process.waitFor(); System.out.println("Process exitValue: " + exitVal); } catch (InterruptedException e) { e.printStackTrace(); } }
第二种:使用jdk自带的rt.jar中的javax.tools包提供的编译器
/** * 编译java类 * 使用rt.jar中的javax.tools包提供的编译器 * @param name 类的全限定包名 不带后缀 例如com.test.Notice 而不要写成com.test.Notice.java * @throws java.io.IOException */ public static void compiler(String name) throws IOException { String javaPackageName = name.replace(".",File.separator)+".java"; String javaAbsolutePath = classPath+javaPackageName; JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); compiler.run(null,null,null,"-encoding","UTF-8","-classpath",jarAbsolutePath.toString(),javaAbsolutePath); }
二、使用Class.forName("");将class文件加载到内存中,并得到该类的class对象
/** * 动态编译一个java源文件并加载编译生成的class * @param name 类的全限定包名 不带后缀 例如com.test.Notice 而不要写成com.test.Notice.java * @throws java.io.IOException */ public static Class<?> dynamicLoadClass(String name) throws IOException, ClassNotFoundException { if (!isClassExist(name)){ compiler(name); } if(isJavaExist(name)){ if(!FileUtil.destroyFile(classPath + name.replace(".",File.separator)+".java")){ System.out.println("========================================>>>>删除源文件失败!"); } } return Class.forName(name); }
以下是全部代码:
package com.basic.core.classloader; import com.basic.core.util.FileUtil; import sun.tools.jar.Main; import javax.tools.JavaCompiler; import javax.tools.ToolProvider; import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; /** * desc:自定义的类加载器,用于实现类的动态加载 */ public class MyClassLoader extends ClassLoader { //类路径 private static String classPath ; private static String jarPrefix; private static StringBuilder jarAbsolutePath; static{ classPath = MyClassLoader.class.getClassLoader().getResource("").getPath(); classPath = !classPath.startsWith("/")?classPath:classPath.substring(1);//去掉开始位置的/ classPath = classPath.endsWith(File.separator)?classPath:classPath+File.separator; jarPrefix = classPath.substring(0,classPath.lastIndexOf("classes"))+File.separator+"lib"+File.separator; jarAbsolutePath = new StringBuilder().append(jarPrefix) .append("hibernate-core-4.2.0.Final.jar;") .append(jarPrefix).append("hibernate-jpa-2.0-api-1.0.1.Final.jar;") .append(jarPrefix).append("validation-api-1.0.0.GA.jar;"); } /** * 如果父的类加载器中都找不到name指定的类, * 就会调用这个方法去从磁盘上加载一个类 * @param name 类的全限定包名 不带后缀 例如com.test.Notice 而不要写成com.test.Notice.java * @return * @throws java.io.IOException */ @Override protected Class<?> findClass(String name) throws ClassNotFoundException { byte[] classBytes = null; Class<?> clazz = null; try { //加载类的字节码 classBytes = loadClassBytes(name); //将字节码交给JVM clazz = defineClass(name,classBytes,0,classBytes.length); if(clazz == null){ throw new ClassNotFoundException(name); } } catch (IOException e) { e.printStackTrace(); } return clazz; } /** * 加载类的字节码 * @param name 类的全限定包名 不带后缀 例如com.test.Notice 而不要写成com.test.Notice.java * @return * @throws java.io.IOException */ private byte[] loadClassBytes(String name) throws IOException { String classPackageName = name.replace(".",File.separator)+".class"; String classAbsolutePath = classPath+classPackageName; //编译java文件 javac(name); byte[] bytes = Files.readAllBytes(Paths.get(classAbsolutePath)); return bytes; } /** * 指定的类的class是否存在 * @param name * @return * @throws IOException */ public static boolean isClassExist(String name) throws IOException { String classPackageName = name.replace(".",File.separator)+".class"; return FileUtil.isExists(classPath+classPackageName)?true:false; } /** * 指定的类是否存在 * @param name * @return * @throws IOException */ public static boolean isJavaExist(String name) throws IOException { String classPackageName = name.replace(".",File.separator)+".java"; return FileUtil.isExists(classPath+classPackageName)?true:false; } /** * 编译java类 * 使用Runtime执行javac命令 * @param name 类的全限定包名 不带后缀 例如com.test.Notice 而不要写成com.test.Notice.java * @throws java.io.IOException */ public static void javac(String name) throws IOException { String javaPackageName = name.replace(".",File.separator)+".java"; String javaAbsolutePath = classPath+javaPackageName; Process process = Runtime.getRuntime().exec("javac -classpath "+ jarAbsolutePath+ " " + javaAbsolutePath); try { InputStream errorStream = process.getErrorStream(); InputStreamReader inputStreamReader = new InputStreamReader(errorStream); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String line = null; while ((line=bufferedReader.readLine()) != null){ System.out.println(line); } int exitVal = process.waitFor(); System.out.println("Process exitValue: " + exitVal); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 编译java类 * 使用rt.jar中的javax.tools包提供的编译器 * @param name 类的全限定包名 不带后缀 例如com.test.Notice 而不要写成com.test.Notice.java * @throws java.io.IOException */ public static void compiler(String name) throws IOException { String javaPackageName = name.replace(".",File.separator)+".java"; String javaAbsolutePath = classPath+javaPackageName; JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); compiler.run(null,null,null,"-encoding","UTF-8","-classpath",jarAbsolutePath.toString(),javaAbsolutePath); } /** * 动态编译一个java源文件并加载编译生成的class * @param name 类的全限定包名 不带后缀 例如com.test.Notice 而不要写成com.test.Notice.java * @throws java.io.IOException */ public static Class<?> dynamicLoadClass(String name) throws IOException, ClassNotFoundException { if (!isClassExist(name)){ compiler(name); } if(isJavaExist(name)){ if(!FileUtil.destroyFile(classPath + name.replace(".",File.separator)+".java")){ System.out.println("========================================>>>>删除源文件失败!"); } } return Class.forName(name); } public static void main (String[] args){ } }