资讯详情

资讯详情

jvm专题

# jvm双亲委派机制jvm一共有三种类加载器启动类加载器扩展类加载器和应用类加载器。启动类加载器主要是加载JAVA核心类库而扩展类的话主要是用于去加载扩展包里面的类。那么应用类加载器就是加载开发者自定义的类是什么双亲委派指的是当要加载一个类的时候是要先从应用类加载器开始加载而应用类加载器会先不加载而是去问它的父类加载器扩展类加载器能不能加载扩展类加载器再去问他的父类启动类加载器能不能加载如果父类加载器不能加载的话再由子类加载器加载否则就是父类加载器直接加载。为什么使用双亲委派机制就是为了能够保障类加载的唯一性以及安全性。保证同一个类在jvm里面是唯一的而且防止开发者自定义的类覆盖掉JAVA的核心类。打破双亲委派一个 Tomcat 跑多个 Web 应用AppA 用 spring-webmvc 5AppB 用 spring-webmvc 6都叫 org.springframework.web.servlet.DispatcherServlet如果严格双亲委派父加载器加载一次全容器共享 → 版本冲突、NoSuchMethodError。所以 Tomcat 需要应用之间隔离各自加载自己的类tomcat如何打破双亲委派的Tomcat 通过给每个 Web 应用创建独立的类加载器 WebAppClassLoader。因为需要改变类加载顺序、实现隔离或热部署所以需要重写 loadClass 并且必须严格控制哪些类走父加载器、哪些类自己加载否则会破坏 JVM 的类安全机制。jdk9以后双亲委派的改变JDK 9 引入模块化后每个模块在编译时就会声明自己包含哪些包因此类加载器收到加载请求时可以先根据类的包名查出它归属于哪个系统模块比如java.lang属于java.base从而直接交给负责该模块的加载器通常是启动类加载器去加载省去了以往逐层向上委派的盲目过程而对于用户自定义类由于java.*等核心包已被java.base等系统模块独占用户代码在编译期就无法向这些包中定义类javac会报包存在于另一个模块中即便绕过编译运行时加载器也会基于模块归属检查拒绝加载不属于该模块的java.*类从而在编译和加载两个层面彻底杜绝了用户自定义类覆盖核心类的可能。应用类加载器不会去加载java.lang包下的任何类哪怕是你自己定义的。因为java.*包在 JVM 层面有硬性限制只有引导类加载器和平台类加载器才有资格定义java.*类。当应用类加载器试图定义java.lang.String时会直接抛出SecurityException: Prohibited package name根本轮不到它“加载成功”。所以应用类加载器的职责范围天然就排除了java.*包。java内存模型垃圾回收机制jvm内存结构OOM如何排查
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →