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

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

时间:2018-11-08
浏览:15725
发布:甲骨文华育兴业
赞: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之路开启梦想之门!


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


相关推荐

java开发培训

Java集合类框架的基本接口有哪些

在JAVA开发中框架给我们提供了很多方便的接口,但是接口到底是什么呢?在开发中又起到了什么作用呢,这就是我们今天需要了解的!

java开发培训

内存模型是怎么解决缓存一致性问题的?

由于CPU和主存的处理速度上存在一定差别,为了匹配这种差距,提升计算机能力,人们在CPU和主存之间增加了多层高速缓存。每个CPU会有L1、L2甚至L3缓存,在多核计算机中会有多个CPU,那么就会存在多套缓存,那么这多套缓存之间的数据就可能出现不一致的现象。为了解决这个问题,有了内存模型。内存模型定义了共享内存系统中多线程程序读写操作行为的规范。通过这些规则来规范对内存的读写操作,从而保证指令执行的正确性。

java开发培训

简单的 Java 性能调优技巧

​大多数JAVA开发人员理所当然地以为性能优化很复杂,需要大量的经验和知识。好吧,不能说这是完全错误的。优化应用程序以获得最佳性能不是一件容易的事情。但是,这并不意味着如果你不具备这些知识,就不能做任何事情。这里有一些易于遵循的调优方式,大家可以做个参考!

java开发培训

分代收集算法

当前商业虚拟机的垃圾收集都采用“分代收集”(Generational Collection)算法,这种算法并没有什么新的思想,只是根据对象存活周期的不同将内存划分为几块。一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适合的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成。而老年代中因为对象存活率高、没有额外空间对他进行分配担保,就必须使用“标记-清理”或者“标记-整理”算法来进行回收。

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

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

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

网站地图