快乐学习 一个网站喵查铺子(catpuzi.com)全搞定~

java中为什么要有垃圾回收机制

编程杂谈 尔雅学习君 2023-09-08 扫描二维码
文章目录[隐藏]

有时,在网上能看到这样一道题目“java中为什么要有垃圾回收?”。每个人都有各自的理解,答案也千奇百怪,基本的思路都是垃圾回收防止内存泄漏。最近,看了一点技术资料,进行稍微深入一点的学习,把自己的理解也与大家分享。

java在计算机中的存储

java在运行时,数据在计算机中是如何存储的?这比C语言的“寄存器+内存块”可复杂多了。不同语言的设计理念差异会导致底层实现上有较大的不同。

寄存器

寄存器,是最快的存储区,是在CPU内部的,在操作系统的课堂上学过。你不能修改和控制它,是执行指令的地方。

堆栈

堆栈,位于RAM(随机访问存储器)中,即内存中。java系统确切管理存储在堆栈内的所有项的生命周期,注意是确切。也就是说,java系统能精确知道和控制所有项的创建和释放。

堆,也位于RAM(随机访问存储器)中,即内存中,是一种通用的内存池。既然叫“池”,那么它就比较大,用于存放java的对象。堆不同于堆栈的地方是:不需要知道存储的数据在堆里存活多少时间,这样带来的好处是灵活性和工作效率的提升。在工作时,你只需要声明对象,然后分配空间即可,不用在分配时就去考虑释放问题。这点想想写C程序的时候,你创建一个对象,立即就需要想着找个地方先写释放代码,之后才是写这个对象的逻辑运算。

常量存储

常量,是无需改变的,同代码一样,那么就挤在程序代码中吧,也就是存储在堆栈中。在嵌入式系统中,也可以放在ROM(只读存储器)中。

非RAM存储

非RAM存储,指的是网络和磁盘。这类数据独立于程序之外,不受控制也能长久存在。流对象,对象转化为字节流,在网络上流转。持久化对象,存储于磁盘上。

垃圾回收

基本类型

java是面向对象编程(OOP)。java将一切视为对象,都是从Object类衍生而来,是单根继承。但还有一系列特殊的类型,称为基本类型。他们是小的、简单的变量,若是按照对象处理则并不高效,所以基本类型是声明类型,然后存储“值”。基本类型是创建在堆栈上,是被java系统确切控制的,其生命周期是受作用域控制,而作用域由花括号的位置决定。这点就同面向过程的编程语言中变量一样。

基本类型有9种,boolean、char、byte、short、int、long、float、double、void,也有相应的包装器类型转化为对象,以便在容器中使用。

基本类型是创建在堆栈上,没有垃圾回收的。

引用

先看一段代码。

String s = new String(“hello”);
s 就是引用。引用相当于操作对象的标识符,基于底层实现的假设可以理解为指针。既然引用是一个标识符,那么它的大小是可控的,所以引用也是创建在堆栈上,是被java系统确切控制的。其生命周期是受作用域控制。

引用是创建在堆栈上,没有垃圾回收的。

对象
在上述代码中,String(“hello”) 就是对象,是通过操作符 new 创建的,然后由引用 s 指向。为什么说的这么啰嗦呢?无非是想强调对象的生命周期不受作用域的控制,由 new 创建的对象,只要需要,就可以一直保留下去。那么若超出作用域范围 {},则引用就会释放,但我们可以在不同作用域间传递和复制对象引用。这样,成本可就小多了。java对象很符合堆的特点,也就在堆上完成对象的管理了(实在不好说清,堆和对象的因果关系)。

如果java让对象持续存在,那么就会只增不减,逐渐填满内存空间,进而阻塞应用程序。换个角度说,也就是由于java对象不受作用域的控制,那么就存在着一种可能,对象的所有引用都已经释放了,但对象还活着,已无用了。此时的对象就像一个孤儿,占据着内存空间却无所依靠。从内存的角度看,则是这块内存区域将无法被再次使用,就像是泄漏了一样。在C语言中,new一个对象后,由于某些原因(忘记了或异常逻辑导致跳过)却没有free对象就是这种情况。所以,java中引入了垃圾回收机制,即由java系统控制,周期性对堆中的对象进行扫描,识别出这些孤儿,然后进行释放。在C++中,也有类似的机制,叫做智能指针。

对象是创建在堆上,拥有垃圾回收机制以防止内存泄漏。

喜欢 (0)
关于作者: