探索JVM底层奥秘之ClassLoader
JVM 运行流程
1.如何跨平台
(JVM针对不同的平台生成不同的虚拟机)
Java源程序通过 Javac编程生成.class文件,
加载到JVM内存的堆中,通过被JVM解析成能被不同平台支持的指令,
2. JVM基本结构
类加载器 ClassLoader 符合要求负责加载到内存中
执行引擎 execution engine 负责运行 解析
运行数据区 核心
本地接口 native 被 native 对融合不同开发语言的原生库为JAVA所用 无需重复开发
3.类的装载 :
加载,连接 (验证,准备,解析),初始化,使用,卸载
class存储类的结构 堆中
初始化: 执行类的构造器<clinit> 为类的静态变量和静态代码块初始化值
安源码的顺序执行,如果静态代码块在前,则,只能写不能读 反之没要求
构造器是构造类的
构造方法是实例化对象
先执行构造器,
通过父类的加载器先加载,
4.为什么 类的加载器是双亲委派模型
避免重复加载 首先父类的类加载先加载,如果没找到,在去找发起者的类加载器,
避免重复加载,父类加载器已经加载成功,子类的类加载器无需再次加载 安全,String是根类加载的 Obj
5.有哪些类加载器 常用的
JDK 已有的类加载器
- BootStrapClassloader JVM的启动加载器 自启的 c++写的 >>主要加载 rt.jar 一堆jar 在java中用Null代替
- Extensionclassloader 加载%lib/ext/*.jar%
- Appclassloader 都是继承的 classpath
- 自定义类加载器 自定义的加载路径 重写findclass方法实现自定义类加载器
6.类加载器在底层存放在什么地方呢?
java.lang.ClassLoader.class
传的是类的二进制字节流 包名加类名
/ /首先,检查是否已经加载了类
Class<?> c = findLoadedClass(name);
自定义类加载器 重点是重写findclass方法
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class MyclassLoader extends ClassLoader{
private String path; //加载类的路径
private String name;
public MyclassLoader(String path, String name) {
super(); //让系统类加载器成为该类的父类
this.path = path;
this.name = name;
}
public MyclassLoader(ClassLoader parent,String path, String name) {
super(parent);
this.path = path;
this.name = name;
}
/*
* 加载定义的类
*
* */
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
// TODO Auto-generated method stub
byte[] data = null;
try {
data = readClassFileToByteArray(name);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return this.defineClass(name, data, 0, data.length);
}
/*
* 获取。class文件的字节数组
*
*
* */
private byte[] readClassFileToByteArray(String name2) throws IOException {
InputStream is=null;
byte[]returnData=null;
name = name.replaceAll("\\.","/");
String filePath=this.path+ name +".class";
File file=new File(filePath);
ByteArrayOutputStream os=new ByteArrayOutputStream();
try {
is=new FileInputStream(file);
int tmp=0;
while((tmp =is.read())!= -1){
os.write(tmp);
}
returnData=os.toByteArray();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
is.close();
os.close();
}
return returnData;
// TODO Auto-generated method stub
}
}