SpringBoot热部署
- 添加devtools依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
-
修改相关配置
步骤1
步骤2
注意事项:
代码修改后需要 离开idea 才会生效,例如:修改代码后,浏览器进行刷新,能看到程序在重新启动
java源码到JVM过程
类加载器ClassLoader
ClassLoader加载class文件到JVM步骤:
1.加载class文件
2.链接
3.初始化
4.使用
5.销毁
四个ClassLoader对象
- BootStrapClassLoader启动类加载器 :负责加载JAVA核心类库
- ExtClassLoader标准扩展类加载器:负责java.ext包
- AppClassLoader系统类加载器:负责classpath下的类
- CustomClassLoader:自定义类加载器
父子关系(不等于继承关系)
双亲委派机制:
某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载
委托机制的意义 — 防止内存中出现多份同样的字节码
defineClass:将class文件转换为JVM中的引用
loadClass:返回存在于JVM中的引用
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// 判断JVM中是否存在该类的引用
Class<?> c = findLoadedClass(name);
// 如果没有,classLoader尝试加载该类
if (c == null) {
long t0 = System.nanoTime();
try {
// private final ClassLoader parent;
//判断是否存在父类加载器,父类加载器进行加载(递归)
if (parent != null) {
c = parent.loadClass(name, false);
} else {
// BootStrapClassLoader进行加载
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
因此,要实现热部署,必须打破双亲委派(因为同一个类只存在一份该类的字节码),自己定义类加载器
自定义类加载器
public Class<?> loadClass(String name) throws ClassNotFoundException {
// TODO 加锁
Class<?> c = findLoadedClass(name);
if (c == null) {
// 不需要我们加载
if (!clazz.contains(name)) {
c = getSystemClassLoader().loadClass(name);
} else {
throw new ClassNotFoundException("找不到该class");
}
}
return c;
}
private void loadClassPath(File file) throws IOException {
if (file.isDirectory()) {
for (File file1 : file.listFiles()) {
loadClassPath(file1);
}
} else {
String fileName = file.getName();
String filePath = file.getPath();
String endName = fileName.substring(fileName.lastIndexOf(".") + 1);
if ("class".equals(endName)) {
InputStream inputStream = new FileInputStream(file);
byte[] data = new byte[(int) file.length()];
inputStream.read(data);
String className = filePathToClassName(filePath);
clazz.add(className);
defineClass(className, data, 0, data.length);
}
}
}











网友评论