类装载器(ClassLoader)主要负责加载class文件,是否能执行主要取决于execution engine它是负责执行被加载类中包含的指令。有两种类加载器分别为启动类加载器和用户自定义类加载器,然而启动类加载器是JVM实现的一部分,用户自定义类加载器是Java程序一部分。
栈:栈有时我们又叫栈内存,负责Java程序的运行,它是在线程创建时创建的,所以生命周期也是和线程生命周期一致,同时消亡,线程结束了栈也就释放。方法运行时需要为其开辟一块内存区域,也就是栈帧,栈帧包含局部变量表(存放该方法的局部变量,为引用时实例存储在堆中)、操作数栈、动态链接、方法出口。
本地方法:使用native关键字修饰的函数(方法),说明这个方法是原生函数,也就是这个方法是用C/C++语言实现的,并且被编译成了DLL,由java去调用。
程序计数器:是指方法区中的方法字节码由引擎读取下一条指令,它是一个非常小的内存空间。为什么有这种东西呢,大家都知道每个线程都是有一个程序计数器的,是线程私有的,相当一个指针,当程序在线程之间跳动时,就需要他来标注返回的位置。
方法区:是指线程共享的,谁都可以共享使用,我们通常用来保存装载类的元结构信息、常量、静态变量(为引用时实例存储在堆中)
堆(heap)它是Java虚拟机用来存储对象实例的,比我们在开发过程使用的new对象,只要通过new创建的对象的内存的对象都在堆分配,注意一点的是堆中的对象内存需要等待垃圾器(GC)进行回收,也是Java虚拟机共享区。
新new的对象放在Eden区,Eden区满后进行一次minor gc,将垃圾对象(可达性分析,引用计数分析)清除,并把依然存活的对象放入(通过复制算法)Survivor from区;当Eden区再次满,再一次minor gc,这时是对Eden区和from区都做minor gc,这时依然存活的对象都放入to区,下一次minor gc依然存活的对象放入到from区…如此在from 和 to之间反复,直到分代年龄达到15,则将这些经常不死的对象放入老年区。
对象优先在新生代分配,但是有的情况对象直接在老年代分配,如下:
1、分配的对象大小大于eden space。适合所有收集器。
2、eden space剩余空间不足分配,且需要分配对象内存大小不小于eden space总空间的一半,直接分配到老年代,不触发Minor GC。
3、大对象直接进入老年代
当整个堆放满之后对整个堆进行一次full gc,如果执行完full gc后仍然满的话则抛出堆内存溢出异常。jvm调优就是合理设置各个区的大小,达到减少full gc的次数的目的。