线程池详解

线程池详解

Posted by bulingfeng on August 5, 2024

简介

双亲委派加载机制的意义是什么呢?

减少相同类的创建,代码功能的完整性和一致性。还有个原因就是有人恶意创建一些类来对程序进行恶意攻击。

而在谈双亲委派之前,还是要谈谈类的加载过程。

类的加载

1、验证阶段;JVM会校验.class文件是否符合JVM规范。

2、准备阶段;给静态变量赋值给默认值。如果是加final的静态变量,则直接赋值完成。比如public static final a=1; 那么直接赋值给a变量为1;请注意通过new创建的对象并不是在这里复制。

3、解析阶段;把字节码的常量池中的一些引用给变成直接引用,这样的变量都可以被访问到了。

4、初始化;把静态变量的值给初始化。

双亲委派

根据类的加载描述,双亲委派的这个过程应该是在验证的时候完成的。

class文件进行双亲委派的时候,是一层层开始进行寻找和加载的。

比如现在要加载一个类,其实就是从应用加载起开始,一级级向上委派,直到到最顶层的父类,然后开始判断是否有改类,如果有就进行加载,没有就继续向下进行加载,直到加载到该类为止,如果没有加载到就抛出来ClassNotFoundException。

总结:

其实就是越是顶层的父类的优先级越高,即同样的加载器有同样的包名和类名,那么肯定是父类先加载这个类,而下面的子加载器则不会加载到这个类。

自定义加载器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class FileSystemClassLoader extends ClassLoader {
  private String rootDir;
  public FileSystemClassLoader(String rootDir) {
    this.rootDir = rootDir;
  }

  @Override
  protected Class<?> findClass(String name) throws ClassNotFoundException {
    String path = rootDir + File.separatorChar
        + name.replace('.', File.separatorChar) + ".class";
    byte[] bytecode = null;;
    try (InputStream input = new FileInputStream(path)) {
      ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
      byte[] buffer = new byte[4096];
      int readSize = 0;
      while ((readSize = input.read(buffer)) != -1) {
        byteStream.write(buffer, 0, readSize);
      }
      bytecode = byteStream.toByteArray();
    } catch (FileNotFoundException | IOException e) {
      e.printStackTrace();
    }

    if (bytecode == null) {
      throw new ClassNotFoundException("class name: " + name);
    } else {
      return defineClass(name, bytecode, 0, bytecode.length);
    }
  }
}

问题

当一个Tomcat部署多个项目时,如果多个项目包含全限定名相同的类该怎么办?

Tomcat会为每个web应用创建一个类加载器,这几个类加载器之间是隔离的。