深入理解JVM(一)——java内存区域

概述

对于java程序来说,由虚拟机管理内存,在虚拟机自动内存管理的机制下,一旦出现内存泄漏和溢出方面的问题,如果不了解java虚拟机是怎么使用内存的,那么排查错误会非常困难。

1.运行时数据区域

Java虚拟机在执行Java过程中会把管理的内存划分为若干个不同的数据区域。

1.1 程序计数器

程序计数器(处于线程独)占区是一个非常小的内存空间,它可以看成是当前线程所执行的字节码的行号指示器。如果线程执行的是java方法,这个计数器记录的是正在执行的虚拟字节码指令的地址。如果正在执行的是native方法,那么这个计数器的值为空(Undefined)。此区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。

1.2 Java虚拟机栈

Java虚拟机栈也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的动态内存模型。
栈帧(Stack Frame):用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法从调用到执行过程都对应一个栈帧在虚拟机中入栈到出栈的过程。
局部变量表:存放编译期可知的各种基本数据类型,对象引用(reference类型)和returnAddress类型(指向一条字节码指令的地址),局部变量表的大小在编译期便已经可以确定,在运行时期不会发生改变。
两种异常情况:如果线程请求的栈深度大于虚拟机所允许的深度,抛出StackOverflowError异常;如果扩展时无法申请到足够内存,会抛出OutOfMemoryError异常。

1.3 本地方法栈

本地方法栈为虚拟机执行native方法服务。
与虚拟机一样本地方栈也会抛出StackOverflowErrorOutOfMemoryError异常

1.4 Java堆

Java堆(Java Heap)是Java虚拟机所管理内存中最大的一块。Java堆是被所有线程共享的一块区域,在虚拟机启动时创建。存放对象实例。Java堆是垃圾收集器管理的主要区域,采用分代收集算法,所以可以分为新生代(由EdenSurvivor Space 组成)和老年代。Java堆可以固定大小,也可以扩展(通过**-Xmx** 和 -Xms控制),如果堆中没有内存完成实例分配分配,并且无法扩展时会抛出OutOfMemoryError异常。

1.5 方法区

方法区(Method Area),别名Non-Heap(非堆),各线程共享,用于存储一杯虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
方法区与永久代实际并不等价,对于HotSpot中才有永久代的概念

1.6 运行时常量池

每一个运行时常量池(Constant Pool Table)都在java虚拟机的方法区中分配,用于存放编译生成的各种字面量和符号引用。
例如在Java中字符串的创建会在常量池(方法区中StringTable:HashSet)中进行。

1.7 直接内存

直接内存(Direct Memory)不是虚拟机运行时数据区中的,也不是Java虚拟机中的内存区域。
jdk1.4中增加了NIO,引入基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存(系统内存替代用户内存),提高了性能。

2.HotSpot虚拟机对象

HotSpot VM是Sun JDK和OpenJDK中所带的虚拟机,也是目前使用范围最广的Java虚拟机

2.1 对象的创建

创建对象通常new关键字,而在虚拟机中,首先检查这个指令的参数是否在常量池中定位到一类的符号引用,并检测符号引用的类是否已被加载解析初始化过。如果没有,则必须先执行相应的类加载过程。在类检查通过后,虚拟机会为新的对象分配内存(位于堆中),所需内存大小在类加载完成后便可完全确定。
内存分配完成后,虚拟机会将分配到的内存空间都初始化为零值(不包括对象头),然后虚拟机要对对象进行必要设置,例如这个对象是哪个类的实例、如何找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息(存在对象的对象头(Object Header))。然后会执行< init >方法,把对象初始化,就此一个对象才算完全产生。

2.2 对象的内存布局

对象头(Header):

  • 自身运行时数据(32位~64位 MarkWord):哈希值、GC分代年龄、锁状态标志、线程持有锁、偏向线程ID、偏向时间戳
存储内容标志位状态
对象哈希码、对象分代年龄01未锁定
指向锁记录的指针00轻量级锁定
指向重量级锁的指针10膨胀(重量级锁定)
空,不需要记录信息11GC标记
偏向线程ID、偏向时间戳、对象分代年龄01可偏向
  • 类型指针(什么类的实例)

实例数据(InstanceData):数据实例,即对象的有效信息,相同宽度(如long和double)的字段被分配在一起,父类属性在子类属性之前。
对齐填充(Padding):占位符填充内存

2.3 对象的访问定位

对象的访问定位有两种方式:句柄访问和直接指针访问
句柄访问:Java堆中会划分出一块内存来作为句柄池,引用变量中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息。一个句柄又包含了两个地址,一个对象实例数据,一个是对象类型数据(这个在方法区中,因为类字节码文件就放在方法区中)。
通过句柄访问对象
直接指针访问:引用变量中存储的就直接是对象地址了,在堆中不会分句柄池,直接指向了对象的地址,对象中包含了对象类型数据的地址。HotSpot采用直接定位
通过直接指针访问对象

2.4 OutOfMemoryError异常

在Java虚拟机规范中,出程序计数器外,虚拟机其他几个运行时区域都会发生OOM异常的可能。

  • Java堆溢出:堆存储实例对象,当对象数量达到最大推容量限制后会内存溢出;(-Xms -Xmx)
  • 虚拟机栈和本地方法栈溢出:单个线程下,无论是由于栈帧太大还是虚拟机栈内容太小,当内存无法分配时,虚拟机抛出的异常都是StackOverflowError异常;(虚拟机栈-xss 本地方法栈-Xoss)
  • 方法区和运行时常量溢出:提示“PerGen space”;(-XX:PermSize -XX:MaxPermSize)
  • 本机直接内存溢出: (-XX:MaxDirectMemorySize,不指定与堆大小一致(-Xmx))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
摘 要 伴随着人才教学的关注度越来越高,对于人才的培养也是当今社会发展的最为重要的问题之一。为了进一步的进行人才的培养关工作,许多的学校或者是教育的机构逐步的开展了网络信息化的教学和和管理工作,通过信息化的手段和技术实现网络信息化的教育及管理模式,通过网络信息化的手段实现在线答题在线考试和学生信息在线的管理等操作。这样更加的快捷解决了人才培养之中的问题,也在进一步的促进了网络信息化教学方式的快速的发展工作。相较于之前的人才教育和培养工作之中,存在这许多的问题和局限性。在学生信息管理方面通过线下管理的形式进行学生信息的管理工作,在此过程之中存在着一定的局限性和低效性,往往一些突发的问题导致其中工作出现错误。导致相关的教育工作受到了一定的阻碍。在学生信息和学生成绩的管理方面,往常的教育模式之下都是采用的是人工线下的进行管理和整理工作,在这一过程之中存在这一定的不安全和低效性,面对与学生基数的越来越大,学生的信息管理也在面领着巨大的挑战,管理人员面领着巨大的学生信息的信息量,运用之前的信息管理方式往往会在统计和登记上出现错误的情况的产生,为后续的管理工作造成了一定的困难。然而通过信息化的管理方式进行对学生信息的管理不仅可以避免这些错误情况的产生还可以进一步的简化学生信息管理工作的流程,节约了大量的人力和物力的之处。在线答题系统的实现不仅给学生的信息管理工作和在线考试带来了方便也进一步的促进了教育事业信息化的发展,从而实现高效化的教学工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值