JDK结构体系:
![]()
JVM是Java Virtual Machine(Java虚拟机)的缩写。是运行在计算机内存中的一个解析Java class文件的核心虚拟机。它首先通过类ClassLoader类的加载机制(双亲委派)把JRE的核心初始启动的类加载到JVM中。保证正常启动运动。
Java的跨平台特性正式由于JVM在不同的操作系统上底层调用的不同硬件指令所实现。
![]()
类加载器和双亲委派机制
1.引导类加载器:负责加载支撑JVM运行的位于JRE的lib目录下的核心类库,比如rt.jar,charsets.jar等。
2.扩展类加载器:负责加载支撑JVM运行的位于JRE的lib目录下的ext扩展目录的JAR类包。
3.应用程序类加载器:负责加载ClassPath路径下的类包,主要就是加载你自己写的那些类。
4.自定义加载器:负责加载用户自定义路径下的类包。
![]()
双亲委派机制其实就是委托自己的父加载器去寻找目标类,找不到的话就加载,如果所有的父加载器都找不到目标类,则在自己的目标路径中加载。
双亲委派机制的好处:1沙箱安全机制:自己写的java.Lang.string.class类不会被加载,这样可以防止核心API被随意篡改。 2.避免重复的类加载:当父亲已经在家该类时,就没有必要子Classloader再加载一次。保证被加载类的唯一性。
全盘委托机制:是指当一个类加载器装载一个类时,显示的是另外一个类加载器加载的,这时就由所依赖的这个类加载器去加载。
注意:同一个JVM中,两个相同包名和类名的类对象可以共存,因为他们的类加载器可以不一样,所以看两个类对象是否是同一个,除了看类对象是否是同一个,包名和类名是否是同一个之外还需要看他们的类加载是否是同一个才能认定他们是他同一个。
下面是一个class文件 进入JVM中 如何运行 垃圾如何处理的 流程分布图。
![]()
JVM内存参数设置
![]()
java -Xms2048M -Xmx2048M -Xmn1024M -Xss512K -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M
-Xss:每个线程的栈大小
-Xms:初始堆大小,默认物理内存的1/64
-Xmx:最大堆大小,默认物理内存的1/4
-Xmn:新生代大小
-XX:NewSize:设置新生代初始大小
-XX:NewRatio:默认2表示新生代占年老代的1/2,占整个堆内存的1/3。
-XX:SurvivorRatio:默认8表示一个survivor区占用1/8的Eden内存,即1/10的新生代内存。
关于元空间的JVM参数有两个:-XX:MetaspaceSize=N和 -XX:MaxMetaspaceSize=N
-XX:MaxMetaspaceSize: 设置元空间最大值, 默认是-1, 即不限制, 或者说只受限于本地内存大小。
-XX:MetaspaceSize: 指定元空间触发Fullgc的初始阈值(元空间无固定初始大小), 以字节为单位,默认是21M左右,达到该值就会触发full gc进行类型卸载, 同时收集器会对该值进行调整: 如果释放了大量的空间, 就适当降低该值; 如果释放了很少的空间, 那么在不超过-XX:MaxMetaspaceSize(如果设置了的话) 的情况下, 适当提高该值。这个跟早期jdk版本的-XX:PermSize参数意思不一样,-XX:PermSize代表永久代的初始容量。
由于调整元空间的大小需要Full GC,这是非常昂贵的操作,如果应用在启动的时候发生大量Full GC,通常都是由于永久代或元空间发生了大小调整,基于这种情况,一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样的值,并设置得比初始值要大,对于8G物理内存的机器来说,一般我会将这两个值都设置为256M。
注意:在JVM优化中,就是尽可能让对象都在新生代里分配和回收,尽量别让太多对象频繁进入老年代。避免频繁对老年代进行垃圾回收,同时给系统充足的内存大小,避免新生代频繁的进行垃圾回收。
对象不大就不会直接进入老年代。