当前位置: 首页>数据库>正文

jvm内存模型

jvm内存模型,第1张
内存模型图

线程私有区域

1.程序计数器

程序计数器是线程私有内存,是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError的区域。它可以看作是当前线程所执行的字节码的行号指示器。程序执行过程中,通过改变这个计数器的值来选取下一条需要执行的字节码指令来完成下一步的操作。每条线程都有一个独立的程序计数器,各线程之间互不影响,独立存储,故称之为线程私有内存。线程私有内存的生命周期与线程相同,线程的结束也就意味着内存生命周期的完结。

2.虚拟机栈

当一个线程被创建时,虚拟机栈也随之被创建,该区域为线程私有,无法被其他线程使用,因此不存在线程安全问题(从一个线程的角度来看,其中的方法执行顺序都是串行;当线程销毁时,该虚拟机栈也随之被销毁,JVM会自动释放该内存区域。虚拟机栈本身是一个先进后出的数据结构。在该线程中,每执行一个方法,就会生成一个栈(Stack Frame),并被压入虚拟机栈,当该方法执行完毕之后,该栈帧会被弹出,也就是说方法调用和方法返回的过程对应着栈帧入站和出栈的操作。

可能抛出的异常:

StackOverflowError:如果线程内请求的栈深度超过虚拟机允许的深度,会抛出该异常。 OutOfMemoryError:如果虚拟机允许动态扩展栈的大小,但是在扩展时无法申请到足够的内存空间,会抛出该异常。

3.本地方法栈

本地方法栈与虚拟机栈所发挥的作用是非常相似的,它们之间的区别不过是虚拟机栈为虚拟机执行java方法,而本地方法栈则为虚拟机执行Native方法。

在Sun HotSpot虚拟机中,直接把本地方法栈和虚拟机栈合二为一。

线程共享区域

1.方法区

方法区与Java 堆一样,也是被所有线程共享的一块内存区域。它用于存储已被虚拟机加载的类信息、常量、静态变量、即使编译器编译后的代码等数据。

运行时常量池:是方法区的一部分,用于存放编译期生成的各种字面量和符号引用。

2.堆

在Java虚拟机中堆是所有线程都可以共享的内存区域,是存放所有类实例和数组对象的地方。在虚拟机启动就根据相关堆参数,创建堆,他也是垃圾收集器工作的主要区域。

堆内存里的对象不会被显式的回收,而是由垃圾回收器回收,为了配合垃圾收集器的特性我们可以把堆分为年轻代和老年代。

StackOverFlow与OOM(OutOfMemory)的区别?StackOverFlow与OOM(OutOfMemory)分别发生在什么时候?

1.StackOverFlow

每当java程序启动一个新的线程时,java虚拟机会为他分配一个栈,java栈以帧为单位保持线程运行状态;当线程调用一个方法时,jvm压入一个新的栈帧到这个线程的栈中,只要这个方法还没返回,这个栈帧就存在。

如果方法的嵌套调用层次太多(如递归调用),随着java栈中的帧的增多,最终导致这个线程的栈中的所有栈帧的大小的总和大于-Xss设置的值,而产生StackOverflowError溢出异常。

2.OutOfMemory

当JVM分配内存时 不够才会抛出异常

java.lang.OutOfMemoryError:Java heap space新建对象时 JVM内存不足 new

java.lang.OutOfMemoryError:GC overhead limit exceedec

GC回收时间过长时会抛出该异常

过长的定义是,超过98%的时间用来做GC并且回收了不到2%的堆内存

连续多次GC都只回收了不到2%的极端情况下才会抛出。

避免恶性循环 浪费CPU性能

java.lang.OutOfMemoryError:Direct buffer memory写NIO程序时经常使用ByteBuffer来读取或者写入数据,这是一种基于通道(channel)与缓冲区(buffer)的I/O方式,他可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用操作,这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据ByteBuffer.allocate(caoability)第一种方式是分配JVM堆内存,属于GC管辖范围,由于需要拷贝所以速度相对较慢ByteBuffer.allocateDirect(caoability) 第2种方式是分配OS本地内存,不属于GC管辖范围,由于不需要内存拷贝所以速度相对较快。但如果不断分配本地内存,堆内存很少使用,那么JVM就不需要执行GC,DirectByteBuffer对象们就不会被回收,这时候堆内存充足,但本地内存可能已经使用光了,再次尝试分配本地内存就会出现OOM

java.lang.OutOfMemoryError:unable to create new native thread导致原因:1.你的应用创建了太多线程,一个应用进程创建多个线程,超过系统承载极限2、你的服务器不允许你的应用程序创建这么多线程,linux系统默认允许单个进程可以创建的线程数是1024个

java.lang.OutOfMemoryError:MetaspceJava 8 之后的版本使用metaspace 来替代永久代metaspace 是方法区在HotSpot中的实现,它与永久代最大的区别在于:metaspace并不在虚拟机内存中而是使用本地内存存储信息如下:虚拟机加载的类信息常量池静态变量即时编译后的代码

JVM栈中存储的是什么?

jvm内存模型,第2张

堆中存储是什么?

存放使用new创建的对象,全局变量


https://www.xamrdz.com/database/6x41995198.html

相关文章: