标签:swap ini des tcl 转换 src 应用程序 java 场景
类加载器机制的层次结构每个 .java 文件都包含着程序的业务逻辑,这些 .java 文件经过 Java 编译器编译成 .class 文件,.class 文件中包含着 Java 代码转换后的虚拟机指令,当需要使用某个类时,虚拟机加载它的 .class 文件,并创建对应的 class 对象,将 .class 文件加载到虚拟机内存,这个过程就成为类加载
将字节码文件加载到内存,并将这些静态数据转换成方法区中的运行时数据结构,在堆中生成一个代表该类的 class 对象,作为方法区数据的访问入口
将 Java 类的二进制代码合并到JVM的运行状态之中的过程
验证:确保加载的类信息符合 JVM 规范,没有安全方面的问题
准备:正式为类变量配内存并设置类变量初始值的阶段,这些内存都将在方法区中进行分配
解析:虚拟机常量池的符号引用替换为字节引用过程
执行类构造器 \<clinit>() 方法的过程,类构造器 \<clinit>() 方法是由编译器自动收藏类中的所有类变量的赋值动作和静态语句块(static块)中的语句合并产生,代码从上往下执行,当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化,虚拟机会保证一个类的 \<clinit>() 方法在多线程环境中被正确加锁和同步
加载 JVM 自身需要的类,它负责将 %JAVA_HOME%/lib 路径下的核心类库或 -Xbootclasspath 参数指定的路径下的jar 包加载到内存中,虚拟机按照文件名识别加载 jar 包,如果文件名不被虚拟机识别,即使丢到 lib 也不被加载,处于安全考虑,启动类加载器只加载包名为 java、javax、sun 等开头的类
扩展类加载器是指 Sun 公司的 sun.misc.Launcher$ExtClassLoader 类,由 Java 语言实现的,是 Launcher 的静态内部类,加载 %JAVA_HOME%/lib/ext 目录下或由系统变量 -Djava.ext.dir 指定位路径中的类库
也叫应用程序加载器是指 Sun 公司实现的 sun.misc.Launcher$AppClassLoader,加载系统类路径 CLASSPATH 或 -D java.class.path 指定路径下的类库,也就是我们经常用到的 CLASSPATH 路径,开发者可以直接使用系统类加载器,一般情况下该类加载是程序中默认的类加载器,通过ClassLoader#getSystemClassLoader() 方法可以获取到该类加载器
除此以外,我们还可以自定义类加载器,但是虚拟机对 class 文件采用按需加载的方式,而且加载某个类时,采用双亲委派模式将请求交由父类处理
如果一个类加载器收到了加载请求,首先它不会去加载,而是将请求委托给自己的父亲去加载,如果他的父亲还存在父亲,就一直向上委托,知道顶层加载器,如果父类加载器可以完成加载请求,就成功返回,如果不行,子加载器才会自己加载
优势:
类加载器之间关系
启动类加载器,由 C++ 实现,没有父类加载器
扩展类加载器,由 Java 实现,父类加载器为 null
系统类加载器,由 Java 实现,父类加载器为扩展类加载器
自定义加载器,父类为系统类加载器
对于Java 应用程序来说,热部署就是在运行时更新Java 类文件
热部署原理:
1、销毁该自定义 ClassLoader
2、更新 class 类文件
3、创建新的ClassLoader去加载更新后的class类文件
热部署与热加载的联系
不重启服务器编译/部署项目
Java热部署与热加载的区别:
部署方式
实现原理
demo
public class MyClassLoader extends ClassLoader {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
// 获取文件名称
String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
// 读取文件流
InputStream is = this.getClass().getResourceAsStream(fileName);
// 读取字节
byte[] bytes = new byte[is.available()];
is.read(bytes);
// 将byte字节流解析成JVM能够识别的Class对象
return defineClass(name, bytes, 0, bytes.length);
} catch (IOException e) {
throw new ClassNotFoundException();
}
}
}
/**
* 热部署入口
*/
public class HotSwap {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, InterruptedException {
loadClass();
System.gc();
// 要修改的字节码
File file1 = new File("C:\\Users\\kernel\\Desktop\\User.class");
// 原字节码
File file2 = new File("D:\\Codes\\Java\\Performance\\jvm-day04\\target\\classes\\com\\kernel\\User.class");
if (!file2.delete())
System.out.println("热部署失败。。。");
// 移动字节码
if (file1.renameTo(file2))
loadClass();
}
public static void loadClass() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
MyClassLoader myClassLoader = new MyClassLoader();
Class<?> aClass = myClassLoader.findClass("com.kernel.User");
Object instance = aClass.newInstance();
Method info = instance.getClass().getMethod("info");
info.invoke(instance);
}
}
标签:swap ini des tcl 转换 src 应用程序 java 场景
原文地址:https://blog.51cto.com/13559120/2384256