zoukankan      html  css  js  c++  java
  • Java的内存区域

    java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外的人想进去。而墙内的人想出来。[来自深入理解java虚拟机]

    对于java程序猿来说,在虚拟机自己主动内存管理机制的帮助下,不须要对每一个new的对象手动释放内存,也不easy触发内存泄漏和内存溢出的问题,可是一旦触发这个问题,假设我们不了解虚拟机对内存的使用原理。是非常难找到问题的。

    所谓java的内存区域。主要是执行时数据区域。java虚拟机在执行java程序时,将它所管理的内存划分成不同的区域,每一个区域有各自的作用对象和生存周期。

    依据java虚拟机规范1.7的规定,把内存划分成这几个部分:程序计数器,java虚拟机栈。本地方法栈。java堆,方法区。如图一所看到的。


    图一  java执行时数据区域

    接下来就分别来描写叙述这几块区域的定义以及作用:

    程序计数器

    程序计数器时一块非常小的内存区域。用来记录线程运行到的位置。

    由于java虚拟机的多线程时通过线程轮流切换和分配处理器运行的方式实现的,所以当一个线程恢复时,可以找到到正常的运行位置。由此可见。此区域也是线程私有的,各个线程之间互不影响。

    java虚拟机栈

    虚拟机栈和程序计数器一样也是线程私有的。生命周期与所属的线程同步。当虚拟机在运行一个方法的同一时候会创建一个栈帧,用来存储局部变量,方法出口,动态链接等信息。一个方法的调用和运行,就相应着一个栈帧从虚拟机栈中入栈和出栈的过程。

    局部变量表中存放基本数据类型。int,boolean,byte,char,short,long,double,float,对象的引用,这些在编译期间她们的大小就是已知的。当运行一个方法时。须要在栈帧中分配多少内存也是固定的。在方法运行的过程中时不变的。

    这个区域可能会出现两种异常:StackOverflowError,OutOfMemoryError,当线程请求的栈深度大于虚拟机同意的最大深度会抛出StackOverflowError异常,只是一般虚拟机都会动态扩展,可是假设扩展时没有足够的内存就会抛出OutOfMemoryError。

    本地方法栈

    本地方法栈和虚拟机栈的作用时相似的,仅仅只是本地方法栈为虚拟机使用到的Native方法服务。有些虚拟机就把本地方法栈和虚拟机栈合二为一了。

    java堆

    java堆与前几块区域不同。它是虚拟机中全部线程共享的一块区域。在虚拟机启动时创建。

    对于大部分应用来说,java堆时虚拟机所管理的内存中最大的一块。用来存放对象实例和数组。

    java堆也是垃圾收集器所管理的基本的区域,因此有时它也被称作GC堆(Garbage Collected Heap)。因为如今的垃圾收集器一般都採用分代收集算法,全部java堆又被分为新生代和老年代,新生代中存活的对象比較少,老年代中存活的对象占大部分,垃圾回收这部分内容在兴许的文章中将会描写叙述。

    另外java堆物理上能够分配在不连续的内存空间中。当没有足够的内存分配实例或数组。而且无法再扩展时,就会抛出OutOfMemoryError。

    方法区

    方法区和堆一样也是线程共享的区域,用于存放已经被虚拟机载入的类信息,常量。静态变量等。它在java虚拟机规范中被描写叙述为java堆的一个逻辑部分。并且对它的限制也比較宽松,比如能够分配在不连续的内存空间上。大小能够扩展也能够固定(不同虚拟机实现不一样)。

    有时,方法区又被称作永久代,可是进入到此区域的数据一样会被回收。

    这个区域的内存回收主要针对常量池的回收和类卸载。

    只是这个部分的回收限制比較多。所以回收的效率比較低。它也会抛出OutOfMemoryError。

    执行时常量池

    执行时常量池时方法区的一部分。

    它用于存放编译期间生成各种字面量和符号引用,在类载入后进入方法区的执行时常量池。

    java虚拟机对Class文件的格式又严格的规定,每一个字节用于存放那种数据都符合规范时才干被虚拟机认可。装载和执行,这部分内容在兴许文章也会有描写叙述。

    执行时常量池还具有动态性,并不是仅仅有在编译期间生成的常量才会放入执行时常量池,执行期间也可能将生成的常量放入当中,比如String类的intern()方法。另外它也会抛出OutOfMemoryError

    直接内存

    直接内存不是java执行时数据去的一部分,也不是虚拟机规范中定义的内存区域,可是它也被频繁的调用,有时也会抛出OutOfMemoryError。

    在JDK1.4之后引用了一种基于通道和缓冲区的IO方式。它使用Native函数库直接分配内存。然后通过存储在java堆中的DirectByteBuffer对象作为内存的引用进行操作,避免了java堆和Native堆中来回复制,提高了性能。

    直接内存不受java堆内存大小的限制。可是也会受设备总内存大小以及处理器寻址空间的限制。

  • 相关阅读:
    软件评测师笔记(十二)—— 口令攻击相关
    软件评测师笔记(十一)—— 可靠性测试相关
    软件评测师笔记(十)—— 安全测试相关
    软件评测师笔记(九)—— 性能测试相关
    【猫狗数据集】利用tensorboard可视化训练和测试过程
    【colab pytorch】使用tensorboardcolab可视化
    【colab pytorch】使用tensorboard可视化
    【colab pytorch】FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy
    【猫狗数据集】使用学习率衰减策略并边训练边测试
    【猫狗数据集】划分验证集并边训练边验证
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/6738110.html
Copyright © 2011-2022 走看看