首先贴图,用图说话,开么见山:
Java虚拟机规范定义的运行时数据区:(引用一下大佬的图)
推荐大佬CSDN:https://www.cnblogs.com/ysocean/p/9345622.html
**五大区域:方法区、堆、虚拟机栈、本地方法栈、程序计算器**
1.程序计数器
记录程序执行位置,一般在字节码也就是JVM指令每一行都会标有一个code也就是一个数字。
dos命令: javap -c .class文件可以查看
作用:
假如在一核cpu中存在了俩个进程分别是进程1和进程2,所以它在处理的过程中进程1和进程2是交替执行的,那么cpu的处理如何定位到具体执行点靠的就是程序计数器来确定执行位置,这里不同线程的程序计数器互不影响。
2.本地方法栈
本地方法栈为虚拟机使用到native方法,为底层的调用,我们都知道java是从c++上面衍生出来的,那么java的底层少不了c++或者c的方法,在java中可以看到很多native修饰的本地方法
3.方法区
线程共享区间,包括:类信息(版本、字段、方法、接口)+运行时常量池(静态变量+常量)
注:方法区的管理设计,HotSpot虚拟机设计团队把Java堆的永生代GC分代收集移植过来进行方法区的内存管理,永生代(PermGen)是有大小限制的,如果类加载多了,会导致内存溢出,即java.lang.OutOfMemoryError: PermGen,因为要和堆的新生代和老年代区分,这里取名永生代。
为了解决不经常出现PermGen内存溢出,JDK1.8时用HotSpot技术将PermGen移出,也就是将永生代移除,方法区移到了Metaspace(元空间),可以说时元空间取代了方法区,元空间处在本地内存中,解决不轻易报错空间的问题,将字符串常量放到了Java Heap,通过GC来回收死亡的对象
HotSpot JDK1.8定义的运行时数据区:(引用一下大佬的图)
这里说一下java虚拟机和HotSpot的区别:java虚拟机是一套标准,可以理解为java虚拟机是java代码的底层接口,而HotSpot是对java虚拟机的一种实现技术,java虚拟机有很多种实现。
4.虚拟机栈
java虚拟机栈是线程独有的一块空间,它随线程而生,随线程而亡
栈的结构图:
当个线程创建后,若在当前线程中调用方法的话,就会生成一个栈帧(一个方法相当于一个栈帧),若有多个方法调用时,就会形成压栈的局面,满足同一线程多个方法的先入后出的原则,先入后出也就是代表方法的开始调用入栈和执行完成后出栈的这一过程。
java虚拟机栈是有大小限制的,他是一个动态的扩展,当然它也可以固定大小,如果在扩展的时候申请不到足够的空间大小的话,就会抛出异常栈溢出:OutOfMemoryError,在代码编译的时候,需要多大的局部变量内存和多深的操作数栈都已经确定好了,空间都是由java虚拟机栈决定的,和运行时的操作无关。
至于栈帧中这几个结构的作用和使用的过程这里篇幅有限,这里我们了解个大概,后面我们会详细,到时候这里会贴地址:https://blog.csdn.net/Mr_xiayijie/article/details/109580673
5.堆
堆是用来存放对象实例的,所有的对象都会存放到堆空间里面,我们都知道对象实例化是要占用空间的,它有一个GC(Garbage Collected Heap)算法(分代收集),相当于是垃圾堆,将朝生夕阳的对象资源进行回收节约空间。
堆空间也是有大小限制的,他是一个动态的扩展,如果在扩展的时候申请不到足够的空间大小的话,就会抛出异常堆溢出:OutOfMemoryError。
这里就会涉及到一个小小的知识点了,对于新手来说就有点懵:
在上面介绍方法区,HotSpot jdk1.8的时候将字符串常量移到了堆上,那么有人就会问,String是一个变量呀,这么可能是个对象,而堆里面存放的是对象,这里科普一些,我们说的变量是指原始数据类型(int,char,boolean、byte、shot....)一共八个,用这些声明的叫变量,String它是个类,它声明的是一个引用对象,例如:String a="123",它是用a作为一个标识,“123”是一个对象,它是用a这个标识来找到“123”这个对象。当然Java提供了封装类(Integer,Byte,Long.....),这是官方划分的哟。
至于堆空间的划分和管理以及如何引用变量这里篇幅有限,这里我们了解个大概,后面我们会详细,到时候这里会贴地址:https://blog.csdn.net/Mr_xiayijie/article/details/109600595