- java 源文件被编译器编译成字节码文件
- JVM 将字节码文件编译成相应操作系统的机器码
- 机器码通过本地方法接口调用相应的操作系统的本地方法库执行相应的方法
1、类加载子系统用于将编译好的 .Class 文件加载到 JVM 中
2、运行时数据区用于存储 JVM 运行过程中产生的数据,包括程序计数器,方法区,本地方法区,虚拟机栈,虚拟机堆
3、执行引擎包括即时编译器JIT和垃圾回收器GC,即时编译器将 Java 字节码编译成具体的机器码,垃圾回收器用于收回在运行过程中不再使用的对象
4、本地接口库用于调用操作系统的本地方法库完成具体的指令操作
类加载过程
—ClassLoader 把字节码.Class 文件加载到内存中,将字节码文件实例化为 Class 对象并进行初始化过程。使用的是双亲委派机制
—先是 Load 加载,Link 链接,Init 初始化
—Load 阶段读取类文件产生二进制流,并转化为特点的数据结构,然后创建 Java.lang.Class 实例(Class 是所有class的类)
—Link 验证 final 是否合规,完成内存布局
— Init 执行类构造方法
—双亲委派机制:Application ClassLoader -> Platform ClassLoader(Java 编写) -> Bookstrap ClassLoader(C++编写)
逐级询问是否已经加载,向下逐级尝试是否可加载
—什么情况下需要自定义类加载器:
隔离加载器,修改类加载方式,扩展加载源,防止源码泄露。
什么情况下主动创建类
- New 一个对象
- 使用类的静态变量
- 使用类的静态方法
- 反射
- 子类导致父类的加载
- 启动类, main方法所在的类
类的连接阶段
- 验证:验证文件格式,元数据验证,字节码验证,符号引用验证
- 准备:为静态变量设置初始值
- 解析:类接口解析,字段的解析,类方法的解析,接口方法的解析
.java 文件由编译器,进行词法分析,语法分析,语义分析,预编译,编译,得到 .class 文件,再由 JVM 的 ClassLoader 加载器通过 双亲委派机制 把.class 文件实例化为 class 对象并初始化,双亲委派机制有三层,最底层是 Bookstrap ClassLoader ,由C++ 编写,中间一层为 platform CLassLoader,最上面一层为 Application ClassLoader ,先是由 Application 逐级询问是否已经加载过这个类,如果没有,则由Bookstrap 层逐级尝试是否加载这个类。
/**
* 自定义类加载器
*/
public class MyClassLoader extends ClassLoader{
/**
*
* @param name 类名
* @param b 字节码数组
* @param off 从数组的哪一位开始读
* @param len 字节码的长度
* @return
*/
public Class<?> defineMyClass(String name, byte[] b, int off, int len){
return super.defineClass(name, b, off, len);
}
}
public class Main {
public static void main(String[] args) throws Exception{
MyClassLoader cl = new MyClassLoader();//创建
byte[] ba = new byte[1024];
InputStream is = null;
int r = 0;
try{
is = new FileInputStream("ClassName.class");
r = is.read(ba);
}finally {
StreamUtil.close(is);
}
cl.defineMyClass(null, ba, 0, r);//字节码转换为对象
Class<?> clazz = cl.loadClass("com.example.class");//加载,类名
Object o = clazz.newInstance();
Method m = clazz.getMethod("");//通过反射调用对象的方法
m.invoke(o);
}
}