一、基础知识
Java从编码到执行
![](https://i-blog.csdnimg.cn/blog_migrate/9f6e4a4e2ea009ca710fa9dd7249ade6.png)
2、从跨平台的语言(java)到跨语言的平台(jvm)
![](https://i-blog.csdnimg.cn/blog_migrate/82a9dd610a497e2249590547e42e622c.png)
3、JVM是一种规范,任何语言只要能编译成class文件,都能在jvm上运行
字节码指令集(汇编语言)
内存管理:栈、堆、方法区等
![](https://i-blog.csdnimg.cn/blog_migrate/a7ed571da17ea76d5670e62fb3623e3b.png)
4、常见的JVM实现
![](https://i-blog.csdnimg.cn/blog_migrate/a82e00eb978d7a5801e44cb57f30ddc4.png)
JDK8以后的Hotspot JVM需要收费,Taobao VM免费
5、JDK JRE JVM
![](https://i-blog.csdnimg.cn/blog_migrate/b4a967046b7d5ebd75cba52e96bd05d5.png)
二、Class File Format
二进制字节流
数据类型: u1u2 u4 u8和_info(表类型)
_info的来源是hotspot源码中的写法
查看16进制格式的ClassFile
sublime / notepad
IDEA插件-BinEd
有很多可以观察ByteCode的方法:
iavap
JBE-可以直接修改
JClassLib -IDEA插件之一
class file 构成
classFile {u4magic;u2minor_version;u2major_version;u2constant_poo1_count;cp_info constant_poo7[constant_poo1_count - 1];u2}
![](https://i-blog.csdnimg.cn/blog_migrate/573742faa5910aa302b7fb87872807aa.png)
![](https://i-blog.csdnimg.cn/blog_migrate/07ad32f6b32ee54fc67b026ea6388e31.png)
![](https://i-blog.csdnimg.cn/blog_migrate/65f1172e308cbee419e0e02f775d848f.png)
三、Class Loading Linking Initializing 类加载-初始化
![](https://i-blog.csdnimg.cn/blog_migrate/3fc509f3b98039c32879c94ada8b1acf.png)
1、加载过程
(1)Loadding 把class文件load到内存(转成二进制字节)
(2)Linking
verification
校验(是否符合Class文件的标准)
preparation
class文件的静态变量赋默认值
resolution
将类、方法、属性等符号引用解析为直接引用
常量池中的各种符号引用解析为指针,偏移量等内存地址的直接引用
(3)Initializing
调用静态代码块,静态成员变量赋初始值
2、类加载器
![](https://i-blog.csdnimg.cn/blog_migrate/2a89db520ecacbc66d59ff1519cadc74.png)
任何一个Class类 Load到内存之后,在内存中占了两块儿内容,一块儿是二进制字节码,另一块儿是Class类的对象,指向了对应的二进制字节码
通过对象去访问二进制文件,这个对象是在metespace(元空间)
启动类加载器(Bootstrap ClassLoader)
负责加载 JAVA_HOME\lib 目录中的,或通过-Xbootclasspath 参数指定路径中的,且被
虚拟机认可(按文件名识别,如 rt.jar)的类。
扩展类加载器(Extension ClassLoader)
负责加载 JAVA_HOME\lib\ext 目录中的,或通过 java.ext.dirs 系统变量指定路径中的类
库。
应用程序类加载器(Application ClassLoader):
负责加载用户路径(classpath)上的类库。
JVM 通过双亲委派模型进行类的加载,当然我们也可以通过继承 java.lang.ClassLoader
实现自定义的类加载器。
![](https://i-blog.csdnimg.cn/blog_migrate/5e0f11e0887368cde51a31ad9716e32b.png)
3、双亲委派
一个孩子向父亲方向,然后父亲向孩子方向的双亲委派过程(双亲:从子到父,从父到子)
作用目的:安全。
主要问题:防止自定义类扰乱。
次要问题:不需要重新加载(防止资源浪费)
简介:
当一个类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父类去完成,每一个层次类加载器都是如此,因此所有的加载请求都应该传送到启动类加载其中,只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径下没有找到所需加载的Class),子类加载器才会尝试自己去加载。采用双亲委派的一个好处是比如加载位于 rt.jar 包中的类 java.lang.Object,不管是哪个加载器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载器最终得到的都是同样一个 Object 对象。
![](https://i-blog.csdnimg.cn/blog_migrate/5b0691b18e30b3820105c655e558c6db.png)
4、类加载器的范围
![](https://i-blog.csdnimg.cn/blog_migrate/c8d1bdc3203d6a14200b9ce46e199351.png)
5、自定义类加载器
自定义的类加载器可以用来加载自己加密后的class
/**
* 自定义类加载器
*/
publicclassZywClassLoaderextendsClassLoader{
/**
* 重写findClass方法
* @param name
* @return
* @throws ClassNotFoundException
*/
@Override
protectedClass<?>findClass(Stringname) throwsClassNotFoundException {
//类的绝对路径目录
Filef=newFile("D:/develop/minnyouzi/src/main/java/com/example/zyw/entity",name.replaceAll(".","/").concat(".class"));
try {
FileInputStreamfis=newFileInputStream(f);
//将文件转换为二进制字节数组
ByteArrayOutputStreambaos=newByteArrayOutputStream();
intb=0;
//从文件中读出来写进字节数组
while ((b=fis.read())!=0){
baos.write(b);
}
byte [] bytes=baos.toByteArray();
baos.close();
fis.close();
/**
* 将二进制字节数组转换为类对象
* name : 转换的类的名字
* bytes:字节数组
* off:字节数组起始的位置
* bytes.length:结束的位置
*/
returndefineClass(name,bytes,0,bytes.length);
}catch (Exceptione){
e.printStackTrace();
}
returnsuper.findClass(name);//throws ClassNotFoundException
}
publicstaticvoidmain(String[] args) throwsException{
ClassLoaderl=newZywClassLoader();
Classclazz=l.loadClass("com.example.zyw.entity.User");
//通过反射访问
Useruser= (User)clazz.newInstance();
user.m();
System.out.println(l.getClass().getClassLoader());
System.out.println(l.getParent());
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/f767bb85c96d2728dee421eb97768ed1.png)
编译
![](https://i-blog.csdnimg.cn/blog_migrate/34becb2dbec66781f09d0e4793ed2874.png)
(1)混合模式
![](https://i-blog.csdnimg.cn/blog_migrate/1890748b2f96b3f25c1dd2ee56482829.png)
(2)lazyloading 懒加载
![](https://i-blog.csdnimg.cn/blog_migrate/ba76c74de9852c35aef2565f6569249b.png)
1.8之前
逻辑上:Method Area方法区:常量池、class各种信息
实际落地在永久代
1.8之后
metespace(元空间)