做有温度的教育!
全国统一咨询热线:400-803-9399
北京
校区
新闻资讯> 技术分享> Java基础之详细理解回收机制

Java基础之详细理解回收机制

时间:2018-11-08
浏览:15867
发布:甲骨文华育兴业
赞:5543

  在以前从事C/C++开发的时候,内存的管理一直是需要被谨慎考虑的内容。在C语言中,我们使用库函数malloc()和free()两个库函数来实现从堆中分配内存与释放,而C++则使用操作符new和delete来实现内存的管理,对于这两个方式,后者是操作符而前者是库函数,后者能够被编译器处理而前者着重于对内部数据实现构造,在面向对象设计中,后者能更好的结合构造函数对自定义对象实现内存分配。但是,在接触了Java之后,我们在内存的管理上可以轻松许多,关键是Java实现了内存的自动管理模式,具体是怎么样的呢?


  一、JVM的内存模型

  要了解Java是如何进行内存回收的,有必要先了解JVM内部的内存模型:

  先来看第一张图:  

甲骨文华育兴业

  这张图基本描述了一个JVM内的运行线程所涉及的5个部分。因为JVM是基于多线程机制的并行计算模型,每个线程有自己独立的内存运行空间,因此线程与线程之间不进行干扰,另一方面虚拟机内存的数据又对所有线程进行共享。是不是有点晕了?先来逐个了解每个组成部分:

  (1)、程序计数器

  程序计数器是用来指向当前的运行线程A在运行指令时,该指令的字节码的位置或行号。在JVM执行多线程并行时,本质是多个线程之间的轮转机制,因为一个CPU同时只能执行一条指令,为了最大化利用CPU的运行资源,于是使用了线程的轮转,当一条线程执行处于闲置状态时,为了防止该线程阻塞后续的线程请求,该线程就会被撤下而替换别的线程,这样可以使得CPU一直在执行从而提高效率。那么当线程A被撤下时,后面肯定还会重新切换上线程A继续执行,该如何得知之前线程被撤下前执行到什么位置了呢?程序计数器就是为了实现这个功能的,它保存了当前执行的字节码在线程内存中的偏移量,从而实现了良好的后续执行。从这里可以得知,每个线程有自己独立的程序计数器内存空间用来指向自己的执行过程,所以这对线程而言是私有的。

  如果一个线程执行的是Java方法,那么程序计数器指向的是虚拟机字节码的指令地址(行号),如果执行的是本地方法,则计数器为空。

  (2)、Java虚拟机栈

  Java虚拟机栈描述的是线程中Java方法执行时的内存模型:每个Java方法在线程内被执行时都会创建一个栈帧,这个栈帧存储局部变量表、操作栈等信息。其中最关键的是局部变量表,该表存储了在执行该Java方法时编译期可知的基本数据类型(short、int、long、byte、char、double、float、boolean)、对象引用类型等。局部变量表的大小在编译期就已经确定了,执行的时候不会修改该表的大小。需要注意的是该表也属于线程私有的。

  (3)、本地方法栈

  既然Java虚拟机栈是为线程中的Java方法服务的,那么本地方法栈就是为线程中执行的本地方法服务的,其存储了本地方法使用是需要用的相关基本数据和其他信息。

  (4)、Java堆

  Java堆是JVM需要维护的最大内存区域。它是对所有的线程进行共享的内存区域。在该区域中,几乎负责了所有的对象实例的内存空间分配以及数组的空间分配。Java堆的JVM进行内存回收的主战场。当前主流的内存回收算法分代算法也是主要在该区域进行内存划分的。该区域主要负责各个对象实例的分配。

  (5)、方法区

  方法区主要用于存储虚拟机加载时加载的类信息、常量数据、静态变量、以及编译器编译后的相关方法的代码。它也是被所有的线程共享的区域。就好比一个类的静态变量在类加载时被加载,并对类共享。这个静态变量或静态方法就存储在方法区中被各个线程需要时调用。

  在方法区中有一个主要构成部分是常量池。该池子里存储的是编译器生成的各种字面量和符号引用。

  说完了以上5个部分,我们再来看下面一张图就容易理解了:  

甲骨文华育兴业

  二、JVM的内存划分

  在了解了以上JVM的内存模型之后,可以对JVM的内存进行有效的划分。这里的划分主要是对Java堆进行划分。因为该部分区域是GC回收的主要战场。在进行内存回收时,Java堆主要划分出2个世代,方法区(非堆)划分出一个世代。这个划分方法是基于垃圾回收的分代回收机制。堆中划分的两个世代分别是Young Generation和Old Generation

  

  而在Young Generation中,又被划分出3个区域,分别是Eden(伊甸园..这名字我也是醉了)、From Suvivor和To Survivor。Eden当中主要是用来给新建立的对象实例开辟内存空间用的,而剩下的两个区域From Survivor和To survivor大小一样,主要是用来存储进行一次垃圾回收之后剩下的对象。

  在Old Genneration当中主要用来存储存活了比较久的对象。

  而在方法区,也就是非堆区,会划分出Permanent Generation,目的是存储一些类信息、静态字段等数据,这些数据会随着类被虚拟机开始加载而存在。基本不参与垃圾回收。


人生从业之路的第一步,从甲骨文华育兴业开始,

背后付出的辛苦与努力只有自己知道,而这也只是职业生涯的开始。

勤恳努力的人终会得到最好的回报,有些努力需要时间来回答

你吃的苦终会铺成你想要的路!

甲骨文华育兴业,为你的IT之路开启梦想之门!


【版权与免责声明】如发现内容存在版权问题,烦请提供相关信息联系我们,我们将及时沟通与处理。本站内容除非来源注明甲骨文华育兴业,否则均为网友转载,涉及言论、版权与本站无关


大数据中hadoop是什么? ps使用 大数据 冲刺Java架构师年薪50W

友情链接: 甲骨文华育兴业太原校区 甲骨文华育兴业济南校区 甲骨文华育兴业哈尔滨校区 甲骨文华育兴业长春校区 魔据教育 音乐培训 青海律师

Copyright ©2016-2019. All Rights Reserved. 京ICP备17018991号-4

网站地图