欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java 内存管理机制,深入理解JVM

程序员文章站 2022-07-15 14:50:48
...

概述:在JVM的自动内存管理机制的支持下,不需要为每一个new的对象进行delete/free。本文将讨论在内存溢出和溢出方面的问题以及数据存放区域。
常见异常:
StackOverFloeError(线程请求栈的深度大于JVM允许的Max Value)
OutOfMemoryError(动态扩展是大于JVM允许的Max Value,注意,这个时候是在扩展,上一个错误是在请求)。

一:数据存放区域。

1.方法区:method Area
这个区域线程共享。存放类加载信息,常量,静态变量,JIT编译后的代码。
里面有运行时常量池,包含符号引用等。
这个区域会出:OutOfMemoryError
2.虚拟机栈 :VM Stack
这个区域是线程私有的。
当方法被执行的时候,这个时候在该区域会创建一个Stack Frame存储局部变量表,操作栈,动态链接,方法出口等信息。一个方法的执行也就意味着一个栈帧在VM Stack里面从入栈到出栈的过程。
这个区域我们着重考虑局部变量表,里面存放了各种的数据类型,只有64位的long和double占用2个局部变量空间,其他的都是一个。
异常:StackOverFloeError,OutOfMemoryError.
3.本地方法栈:Native Method Stack
与虚拟机栈相似,只是他是为Native方法服务,但是虚拟机栈为Java方法(也就是字节码)提供服务。
4.程序计数器:Program Couter Register
该区域较小,可以看做是当前线程的字节码行号指示器,用来选择下一条需要执行的语句。
线程管理:由于线程切换需要恢复到正常的执行的位置,所以一个线程就需要一个程序计数器(线程私有)。
5.堆:Heap
这个区域线程共享。在JVM创建的时候就创建了。对象实例,数组都在这里进行分配。
Java的垃圾回收区域也存放在这个区域(Garbage Collected Heap,采用分代收集算法,详情百度)。
这个区域也会出这个错误:OutOfMemoryError
6.直接内存:Direct Memory
这个区域独立于堆,可以直接使用Native函数分配堆外内存。
每个区域都有创建和销毁的时间,都有各自的用途。
一个面试题:解释内存中的栈(stack)、堆(heap)和方法区(method area)的用法。
答:通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用JVM中的栈空间;而通过new关键字和构造器创建的对象则放在堆空间,堆是垃圾收集器管理的主要区域,由于现在的垃圾收集器都采用分代收集算法,所以堆空间还可以细分为新生代和老生代,再具体一点可以分为Eden、Survivor(又可分为From Survivor和To Survivor)、Tenured;方法区和堆都是各个线程共享的内存区域,用于存储已经被JVM加载的类信息、常量、静态变量、JIT编译器编译后的代码等数据;程序中的字面量(literal)如直接书写的100、”hello”和常量都是放在常量池中,常量池是方法区的一部分,。栈空间操作起来最快但是栈很小,通常大量的对象都是放在堆空间,栈和堆的大小都可以通过JVM的启动参数来进行调整,栈空间用光了会引发*Error,而堆和常量池空间不足则会引发OutOfMemoryError。

二:对象访问。

Object obj = new Object(); // Object obj放在本地变量中,new的对象放在堆里面。
Java 内存管理机制,深入理解JVM
Java 内存管理机制,深入理解JVM

访问方式 句柄访问 直接访问
好处 地址稳定,对象被移动时改变的只是实例化的数据指针,reference本身不修改 速度很快

三:常见的错误产生

 OutOfMemoryError
 模拟条件:while死循环创建对象,导致Heap溢出,产生OutOfMemoryError 
 *
创建大量变量(虚拟栈)