java 自制类加载器的简单实现
package com.xiaomo.reflex;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
public class CompileClassLoader extends ClassLoader{
//读取一个文件的内容
private byte[] getBytes(String filename)throws IOException{
File file = new File(filename);
long len = file.length();
byte[] raw = new byte[(int)len];
try(
FileInputStream fin = new FileInputStream(file);
){
//一次读取Class文件的全部二进制数据
int r = fin.read(raw);
if(r != len){
throw new IOException("无法读取全部文件:"+r+" != "+len);
}
return raw;
}
}
private boolean compile(String javaFile) throws IOException{
System.out.println("CompileClassLoader:正在编译 "+javaFile+"...");
//调用系统的javac命令
Process p = Runtime.getRuntime().exec("javac "+javaFile);
try{
p.waitFor();
}catch (InterruptedException e) {
System.out.println(e);
}
//获取javac线程的退出值
int ret = p.exitValue();
return ret == 0;
}
protected Class<?> findClass(String name) throws ClassNotFoundException{
Class clazz = null;
//将包路径中的点(.)替换成斜线(/)
String fileStub = name.replace(".", "/");
String javaFilename = fileStub + ".java";
String classFilename = fileStub + ".class";
File javaFile = new File(javaFilename);
File classFile = new File(classFilename);
//当指定的java源文件存在,且class文件不存在,或者Java源文件的修改时间比class文件的修改时间更晚时,重新编译
if(javaFile.exists()&&(!classFile.exists()||javaFile.lastModified()>classFile.lastModified())){
try{
//如果编译失败,或者改class文件不存在
if(!compile(javaFilename)||!classFile.exists()){
throw new ClassNotFoundException("ClassNotFoundException:"+javaFilename);
}
}catch (IOException e) {
e.printStackTrace();
}
}
//如果class文件存在,系统负责将该文件转换成class对象
if(classFile.exists()){
try{
//将class文件的二进制数据读入数组
byte[] raw = getBytes(classFilename);
//调用classloader的defineclass方法将二进制数据转换成class对象
clazz = defineClass(name, raw, 0, raw.length);
}catch(IOException e){
e.printStackTrace();
}
}
if(clazz==null){
throw new ClassNotFoundException(name);
}
return clazz;
}
public static void main(String[] args) throws Exception {
//如果运行该程序时没有参数,既没有目标类
if(args.length<1){
System.out.println("缺少目标类,请按如下格式运行java源文件:");
System.out.println("java CompileClassLoader ClassName");
}
//第一个参数是需要运行的类
String progClass = args[0];
//剩下的参数将作为运行目标类的参数
//将这些参数复制到一个新数组中
String[] progArgs = new String[args.length-1];
System.arraycopy(args, 1, progArgs, 0, progArgs.length);
CompileClassLoader cc1 = new CompileClassLoader();
//加载需要运行的类
Class<?> clazz = cc1.loadClass(progClass);
//获取需要运行的类的主要方法
Method main = clazz.getMethod("main",(new String[0]).getClass());
Object argsArray[] = {progArgs};
main.invoke(null, argsArray);
}
}
java 自制类加载器的简单实现的更多相关文章
- Java自定义类加载器与双亲委派模型
其实,双亲委派模型并不复杂.自定义类加载器也不难!随便从网上搜一下就能搜出一大把结果,然后copy一下就能用.但是,如果每次想自定义类加载器就必须搜一遍别人的文章,然后复制,这样显然不行.可是自定义类 ...
- Java虚拟机类加载器及双亲委派机制
所谓的类加载器(Class Loader)就是加载Java类到Java虚拟机中的,前面<面试官,不要再问我"Java虚拟机类加载机制"了>中已经介绍了具体加载class ...
- 深入探讨java的类加载器
类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一.它使得 Java 类可以被动态加载到 Java 虚拟机中并执行.类加载器从 JDK 1.0 就出现了,最初是为了满足 Ja ...
- java自定义类加载器
前言 java反射,最常用的Class.forName()方法.做毕设的时候,接收到代码字符串,通过 JavaCompiler将代码字符串生成A.class文件(存放在classpath下,也就是ec ...
- java 中类加载器
jar 运行过程和类加载机制有关,而类加载机制又和我们自定义的类加载器有关,现在我们先来了解一下双亲委派模式. java 中类加载器分为三个: BootstrapClassLoader 负责加载 ${ ...
- Java 基础 类加载器和双亲委派机制 学习笔记
转自博客:https://blog.csdn.net/weixin_38118016/article/details/79579657 文章不是我写的,但是感觉写的挺通俗易懂的,然后防止以后丢失,就转 ...
- Java 虚拟机类加载器
虚拟机设计团队把类加载阶段张的”通过一个类的全限定名来获取此类的二进制字节流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类.实现这个动作的代码模块称为”类加载器”. ...
- java ClassLoader类加载器
原文 首先来了解一下字节码和class文件的区别: 我们知道,新建一个java对象的时候,JVM要将这个对象对应的字节码加载到内存中,这个字节码的原始信息存放在classpath(就是我们新建Java ...
- java高新技术-类加载器
1.类加载器及委托机制的深入分析 > 类加载器的作用:一个java文件中的出现的类,首先要把这个类的字节码加载到内存中,这个类的信息放在硬盘的classPath下的class文件中, 把cla ...
随机推荐
- android中网络操作使用总结(http)
Android是作为智能手机的操作系统,我们开发的应用,大多数也都须要连接网络,通过网络发送数据.获取数据,因此作为一个应用开发人员必须熟悉怎么进行网络訪问与连接.通常android中进行网络连接通常 ...
- Java基础知识强化22:Java中数据类型转换
数据类型转换: (1). 自动转换 低级变量可以直接转换为高级变量,这叫自动类型转换.比如: byte b: int b: long b: float b: double b: 上面的语句可 ...
- JS和利用openssl的object C加密得到相同的aes加密密文
这是之前接到的一个工作内容,项目原本的登录操作是获得账号和密码以后,对密码进行一遍MD5加密,然后传递账号和密文到cgi文件.在c中获取到账户以后,从数据库中获取到密码,对密码进行一次MD5的加密,然 ...
- jQuery事件与动画
一 事件 1 加载DOM事件 $(document).ready():执行时机:DOM元素准备就绪 执行次数:多次 简单写法:原:$(document).ready(function(){}) ...
- 新浪微博开放平台OAuth授权解决方案(含代码)
前几日一位朋友项目中需要使用新浪微博的接口,故和这位朋友一同研究了新浪微博开放平台上面所提供的资料,首先要使用这些接口是需要用户登录并且授权的,新浪微博开放平台其实是提供两种授权方式的,第一种是:OA ...
- N!水题
//题目是求N!的问题,思路:设定一个整形数组来存放每次计算过后的值 有两个for循环,第一个for循环每次加进一个数 然后在第二个for循环里面计算出此时的阶乘,比如9999,先给出i=2 在第二个 ...
- shell 中 2>&1 的使用
一 相关知识 1)默认地,标准的输入为键盘,但是也可以来自文件或管道(pipe |). 2)默认地,标准的输出为终端(terminal),但是也可以重定向到文件,管道或后引号(backquotes ` ...
- IP V4地址分类
IP V4地址 共分为五类: A类地址范围:1.0.0.1---126.255.255.254 B类地址范围:128.0.0.1---191.255.255.254 C类地址范围:192.0.0.1- ...
- MYSQL Model报错:指定的存储区提供程序在配置中找不到 的解决
开了项目发现没装mysql及mysql connector/.net.下了个最新版本,结果打开vs,进入模型edmx页面就出了这个问题. 刚开始以为是ProviderManifestToken版本的问 ...
- HDU 4611 - Balls Rearrangement(2013MUTC2-1001)(数学,区间压缩)
以前好像是在UVa上貌似做过类似的,mod的剩余,今天比赛的时候受baofeng指点,完成了此道题 此题题意:求sum(|i%A-i%B|)(0<i<N-1) A.B的循环节不同时,会有重 ...