首页 技术 正文
技术 2022年11月13日
0 收藏 312 点赞 4,722 浏览 6071 个字

  如果你想在动态编译并加载了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){ }}

  

 

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,031
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,520
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,368
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,148
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,781
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,861