最简单的 Java 内存管理模型

前言

栈溢出(StackOverFlowError:Java虚拟机栈的内存大小不允许动态扩展,
	当线程请求栈的深度超过当前Java虚拟机栈的最大深度时抛出
内存溢出(OutOfMemoryError:Java虚拟机堆中没有空闲内存,并且垃圾回收器也无法提供更多内存的话就会抛出 

一、内存模型

1.线程私有的

程序计数器(Program Counter Register:
	也被称为PC寄存器,
	一块较小的内存空间,
	当前线程所执行的字节码的行号指示器.
	生命周期同线程,
	唯一不会出现OutOfMemoryError的内存区域
   	
Java虚拟机栈(Java Virtual Machine Stack:
	Java方法执行的内存模型,
	每次方法调用的数据都是通过栈传递的.
	由一个个栈帧组成,
	而每个栈帧都拥有:局部变量表、操作数栈、动态链接、方法出口信息.
	生命周期同线程,
	可能会出现StackOverFlowErrorOutOfMemoryError
        
本地方法栈(Native Method Stacks:  
	为虚拟机使用的本地方法服务.
	方法执行的时候也会创建一个栈帧,
	用于存放本地方法的局部变量表、操作数栈、动态链接、出口信息.
	可能会出现StackOverFlowErrorOutOfMemoryError

2.线程共享的

Java堆(Java Heap):
	虚拟机所管理的内存中最大的一块.
	所有线程共享的一块内存区域,
	在虚拟机启动时创建.
	存放对象实例,
	几乎所有的对象实例都在这里分配内存.
	也是垃圾收集器管理的主要区域,
	也被称为GC(Garbage Collected Heap)堆.
	容易出现的就是OutOfMemoryError 错误
	
方法区(Method Area):
	存储已被虚拟机加载的类信息、常量、静态变量、即编译器编译后的代码等数据.
	别名Non-Heap(非堆),
	也称为永久代(方法区是标准,永久代是实现).
	JDK1.8被移除,用直接内存里的元空间取而代之.
	可能会出现OutOfMemoryError
  			
	运行时常量池(Runtime Constant Pool):
		class文件中除了有类的版本、字段、方法、接口等描述信息,
		还有常量池表(用于存放编译器生成的各种字面量和符号引用).
		属于方法区,
		可能会出现OutOfMemoryError
            
直接内存(Direct Memory):
	并不是虚拟机运行时数据区的一部分,
	也不是虚拟机规范中定义的内存区域,
	但是这部分也被频繁的使用,
	可能会出现OutOfMemoryError
		
元空间(Metaspace):	
	方法区的实现由永久代变成了元空间,
	属于直接内存,
	可能会出现OutOfMemoryError	
	

为什么替换掉方法区:
(1)客观上使用永久代来实现方法区的决定的设计导致了Java应用更容易遇到内存溢出的问题,而且有极少数方法 (例如String::intern())会因永久代的原因而导致不同虚拟机下有不同的表现
(2)主观上当Oracle收购BEA获得了JRockit的所有权后,准备把JRockit中的优秀功能,譬如Java Mission Control管理工具,移植到HotSpot 虚拟机时,但因为两者对方法区实现的差异而面临诸多困难。考虑到HotSpot未来的发展,在JDK 6的时候HotSpot开发团队就有放弃永久代,逐步改为采用本地内存(Native Memory)来实现方法区的计划了,到了JDK 7的HotSpot,已经把原本放在永久代的字符串常量池、静态变量等移出,而到了 JDK 8,终于完全废弃了永久代的概念,改用与JRockit、J9一样在本地内存中实现的元空间(Meta-space)来代替,把JDK 7中永久代还剩余的内容(主要是类型信息)全部移到元空间中

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值