JVM其实是一个Java进程,一个进程在运行过程中,就需要从操作系统中申请到内存资源,JVM把这一块内存划分成几个区域,作为不同的用途.
JVM类加载机制就是把类,从硬盘(文件)加载到内存中,Java程序一开始是编写一个java文件,编译成.class文件(字节码),当运行java程序时,JVM就会读取class文件把文件的内容放到内存中并且构造成class对象.
一个类的生命周期包含以下几个步骤:
总的来说,类的加载就像是准备读一本书,你需要招到这本书,确保它的内容是正确的和可理解的,然后开始阅读.
Java的双亲委派模型是一种类加载的机制,用于保证Java类的安全性和一致性.双亲委派模型描述了类加载过程中,如何找到.class文件.其中JVM自带了三个类加载器.
Bootstrap ClassLoader:负责加载标准中的类,Java有一个标准文档,描述了需要提供哪些类
Extension ClassLoader:负责加载JVM扩展的库,除了标准库之外,实现JVM的厂商会添加一些类
Application ClassLoader:负责加载第三方库,比如mysql,jdbc,servlet,jackson
一个类的加载时机,属于一种懒汉模式,只有被用到了才会加载
垃圾回收是一种自动管理内存泄露的机制,通过周期性的检查和释放不再需要使用的对象来减少内存泄露和提高程序性能…
垃圾回收一般分为两步:
public class Test {
public Object instance = null;
private static int _1MB = 1024 * 1024;
private byte[] bigSize = new byte[2 * _1MB];
public static void testGC() {
//Test实例1被a引用,引用数+1, a的引用数为1
Test a = new Test();
//Test实例2被b引用,引用数+1, b的引用数为1
Test b = new Test();
//a.instance的引用指向b,则a的引用数为2
a.instance = b;
//b.instance的引用指向a,则b的引用数为2
b.instance = a;
//a不再指向Test实例1,引用数-1,a的引用数为1
a = null;
//b不再指向Test实例2,引用数-1,b的引用数为1
b = null;
// 强制jvm进行垃圾回收
System.gc();
}
public static void main(String[] args) {
testGC();
}
}
//此时a和b的两个对象的引用计数不为0,不能被当作垃圾,要想使用对象a就先访问到对象b,要想访问到对象b就得访问到对象a,最终这两个对象无法释放,就会产生内存泄露的问题.
在Java中可以作为GC Root对象有:1.栈上的局部变量.2.常量池里的引用3.方法区的静态成员.
在新生代中,每次垃圾回收都会有大量对象死去,只有少量对象存活,存活下来的对象,通过复制算法继续进行GC,当经历过N次GC后就会进入老年代,老年代对象存活率高,可以通过标记整理的算法继续GC.
新生代:新创建对象进入新生代.
老生代:比较大的对象和经历了N次垃圾回收依然存活下来的对象进入老生代.