JVM学习【2】

【1】Java和C/C++在内存管理方面的区别

区别:垃圾回收机制

C/C++:内存由程序员来申请和释放。
JAVA:Java有虚拟机的自动内存管理机制,不再需要为每一个new操作去写配对的delete/free代码,而且不容易出现内存泄漏和内存溢出问题。也就是说java程序员将内存控制的权利交给了Java虚拟机。
上面已经讲过java程序员将内存控制的权利交给了Java虚拟机,一旦出现内存泄漏和溢出方面的问题,如果不了解虚拟机的使用原理和运行机制的话,排查错误将会异常艰难。

【2】Java运行时数据区

Java虚拟机运行的时候会把它所管理的内存划分成若干不同的数据区域,如下图:
​​​​​​​​在这里插入图片描述
​​​​​​​​​​

(1)程序计数器

A:程序计数器是线程的私有内存。

B:程序计数器是当前线程所执行的字节码的行号指示器,用于指示当前线程所执行的字节码执行到了第几行,字节码解释器在工作时,会改变这个计数器的值来取下一条指令。如果正在执行的是一个java方法,则计数器记录的是正在执行的虚拟机字节码指令地址如果正在执行的是Native方法,则计数器值为空,此内存区域是唯一一个在Java虚拟机规范中没有任何OutOfmemory情况的区域(原因是程序计数器只记录当前指令地址)。

(2)虚拟机栈

A:虚拟机栈是线程私有的内存

B:虚拟机栈的生命周期与线程相同。

C:虚拟机栈描述的是Java方法执行的内存模型,每个方法被执行的时候都会同时创建一个栈帧,用于存储局部变量表,操作栈,动态链接,方法出口等信息。每一个方法被调用直至完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

D:其中,局部变量表存放了编译期可知的各种基本数据类型(boolean,byte,char,short,int,float,long,double),对象引用(reference类型,根据不同的虚拟机的实现,它可能是一个指向对象起始地址的引用指针,也可能指向一个代表对象的句柄或者其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)。

E:其中long和double类型的数据各占两个局部变量空间,其余各占一个。当线程请求的深度大于JVM所允许的深度,会产生StackOverflowError异常。如果虚拟机栈是可动态扩展,扩展时无法申请到足够的内存时,会产生OutofMemoryError异常。(这两种异常在本地方法栈中也存在)

(3)本地方法栈

本地方法栈和虚拟机栈的作用相似

区别:本地方法栈是为虚拟机使用到的Native方法服务,虚拟机栈是为虚拟机执行Java方法(字节码)服务。

(4)Java堆

A:Java堆是Java虚拟机所管理的内存中最大的一块

B:Java堆是被所有线程所共享的一块区域,在虚拟机启动时创建。此内存区域存在的唯一目的就是存放对象实例,几乎所有的对象实例都是在这里分配。

C:Java堆是 垃圾收集管理的主要区域,也被称为GC堆。分类分为:新生代和老年代;再细致一点还有Eden空间,From Survivor空间,To Survivor空间等。线程共享爱国的Java堆中可能划分出多个线程私有的分配缓冲区。

D:Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可。

E:在实现上,既可以实现成固定大小,也可以是扩展的。扩展到无法扩展时,将会抛出OutfMemoryError异常。

(5)方法区

A:各个线程共享的内存区域
B:存储已被虚拟机加载的类信息,常量,静态变量。即时编辑器编译后的代码等数据

(6)运行时常量池

A:属于方法区的一部分
B:常量池用于存放编译器生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。

发布了120 篇原创文章 · 获赞 59 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/lr1916417519/article/details/85006260