文章目录
概述
对于JAVA来说,由JVM(Java Virtual Machine)来管理内存,下面来看下Java虚拟机内存管理
JAVA内存模型介绍
JAVA内存模型,也就是运行时数据区包括堆、元空间、虚拟机栈、本地方法栈、程序计数寄存器。(一堆一元两栈,再加计数器)
堆
堆存储了几乎所有的对象实例,它占用的空间是所有内存区域中最大的,并由垃圾收集器自动回收。内存空间可以固定大小,也可以在运行时动态地调整。初始值和最大值设置方法:-Xms256M -Xmx1024M (ms代表memory start, mx代表memory max,一般设置成一样的大小,减少动态调整)。堆分成新生代和老年代,新产生的对象放入新生代(一个Eden区和两个Survivor区),对象在多次转移之后仍然有引用,则放入老年代。
元空间
JDK8使用元空间代替永久代(PermGen),字符串常量移至堆内存,其他的类元信息、字段、静态属性、方法、常量等移至元空间内。
虚拟机栈
虚拟机栈是方法执行的内存区域,方法执行是栈帧的入栈和出栈的过程。栈的数据结构,只有位于栈顶的当前栈帧才是正在执行的方法。栈帧是方法运行的基本结构。包括操作栈、局部变量表、动态连接、方法出口。
本地方法栈
存放JAVA中声明为native的方法,比如System.currentTimeMillis()。
程序计数寄存器
每个线程创建后都会产生自己的程序计数器和栈帧。程序计数器存放指令的偏移量和行号指示器,线程的中断和恢复依赖程序计数器。
堆中的新生代和老年代是什么?
堆中的内存区域由三部分构成:新生代、老年代、永久代(JAVA8中已取消)。
新生代由一个Eden区和两个Survivor区构成。新生的对象放入新生代,如果多次回收后仍然有引用,则进入老年代。
什么时候执行Minor Collection?什么时候执行Full GC?
新生代被填满后会执行Minor Collection,老年代被填满后会执行Full GC。
哪些是线程共享,哪些是每个线程独立拥有?
堆和元空间是所有线程共享的,虚拟机栈、本地方法栈、程序计数器是线程独立拥有的。
什么是动态连接?
栈帧中包含常量池中对当前方法的引用。每个栈帧都包含一个该栈帧所属方法的引用,这个引用在运行时常量池中。持有这个引用用以支持动态连接(Dynamic Linking)。
Class文件的常量池中有大量的符号引用,这些符号引用一部分在类加载阶段就转化为直接引用,这种转化称为静态解析。另外一部分在运行期间转化为直接引用。
什么是方法返回地址(方法出口)?
一个方法开始执行后有两种方法退出:一种是正常完成,返回值传递给上层调用者;一种是异常完成,不会给上层调用者任何返回值。
无论何种方式,都要返回到被调用位置,程序才能继续执行。返回地址确定方法:调整PC计数器指向方法调用指令后面的一条指令,或者通过异常处理器表来确定。