JVM-内存结构概述

一、 java虚拟机原理

所谓虚拟机,就是一台虚拟的机器。他是一款软件,用来执行一系列虚拟计算指令,大体上虚拟机可以分为
系统虚拟机和程序虚拟机, 大名鼎鼎的Visual Box、Vmare就属于系统虚拟机,他们完全是对物理计算的仿真,提供了一个可以运行完整操作系统的软件平台。
程序虚拟机典型代码就是Java虚拟机,它专门为执行单个计算程序而计算,在Java虚拟机中执行的指令我们成为Java自己码指令。无论是系统虚拟机还是程序虚拟机,在上面运行的软件都被限制于虚拟机提供的资源中。
Java发展至今,出现过很多虚拟机,做初Sun使用的一款叫ClassIc的Java虚拟机,到现在引用最广泛的是HotSpot虚拟机,除了Sum以外,还有BEA的Jrockit,目前Jrockit和HostSopt都被oralce收入旗下,大有整合的趋势。

1.1Java内存模型和java内存结构的混淆:

java内存模型和java内存结构不相同,虽然只差两个字,却没什么关系。
java内存模型是和多线程JMM相关的知识点,二java内存结构是指JVM虚拟机存储空间,所以两者关系不大。

二 、java内存结构

java虚拟机在执行java程序的过程中会把他所管理的内存划分为若干个数据区域。各区域都有各自的用途,和创建和销毁的时间,有些随着程序的启动而存在,有些则依赖用户线程的启动和结束而建立和销毁。所以JVM所管理的内存会包括一下几个运行时数据区域:

方便理解的一张结构图:

java内存结构图

2.1 方法区

方法区,存放的是被static关键字修饰的,常量信息。也可以理解为全局的变量都会放到方法区内,方法区会在被class文件被加载时就会被初始化,放入方法区,而且被线程共享,所以会有线程安全问题。
如果系统定义了太多的类,会导致方法区溢出。虚拟机会抛出内存溢出的错误。
当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。

2.2 java堆

堆内存存放的是:创建出的对象;new创建;数组。堆会被线程共享
java堆是GC的主要区域。由于GC基本都是采用分代收集算法,所以在堆中还可以细分为:新生代、老年代;

  1. 新生代:刚创建的对象,先放到新生代,GC会经常光顾新生代中的对象
  2. 老年代:如果对象频繁的使用,对象放入到老年代中,GC很少会光顾老年代中的对象

再细致一点可以分为:Eden空间、From Survivor空间、To Survivor空间等。无论哪个空间存放的都是对象实例,进一步划分只是方便更好的回收内存,或更快的分配内存。

新生代有三个区域:Eden区、s0区、s1区。

  • 刚创建的对象会放到新生代中的Eden区。
  • s0区域s1区大小相当,目的是垃圾回收机制的复制算法

java堆可以处于物理上不连续的空间中,只要逻辑上是连续的即可,就想磁盘空间一样,在实现时可以固定空间大小,也可以是可扩展的。不过当前主流虚拟机都是按照可扩展实现的(通过-Xmx和-Xms控制)。
如果堆中没有内存完成实例分配,并且堆也无法扩展时,将会抛出OutOfMemorError异常。

2.3 栈

栈内存存放的是:定义的基本局变量,栈内代码运行完毕,便会自动释放内存。栈内存每个线程私有,互不共享,栈内存不会产生线程安全问题。

栈的生命周期与线程相同,每个方法在执行的同时都会创建一个栈帧,用于存储局部变量、操作数帧、动态链接、方法出口等信息。每个方法调用直至执行完毕的过程, 就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

在栈的区域有两种异常状况:
如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;
如果虚拟机栈可以动态扩展,如果扩展时无法申请到足够的内存时,就会抛出OutOfMemoryError异常。(当前大部分java虚拟机都可动态扩展,只不过java虚拟机规范中也允许固定长度的虚拟机栈)

2.4 本地方法栈

本地方法栈和虚拟机栈所发挥的作用非常相似,它们的区别是:
虚拟机栈执行java方法(字节码)服务,而本地方法栈则为虚拟机使用到的Native方法服务。
本地方法栈也会抛出StackOverflowError异常和OutOfMemoryError异常。

2.4 程序计数器

这是一块较小的内存空间,它可以看做当前线程所执行的字节码的行号指示器。字节码解释器工作室就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个技术器来完成。为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各线程之间计数器互不影响,独立存储,所以此区域是线程私有的,也就是线程安全的。

2.5 运行时常量池

运行时常量池是方法区的一部分。存储的是编译期生成的各种字面量和符号引用,这部分将在类加载后进入方法区的运行时常量池中存放。

2.6 直接内存

在深入理解Java虚拟机_JVM高级特性与最佳实践 第2版中看到
直接内存描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值