关于java中的内存回收机制

news2024/10/10 20:21:10

C++中如果创建了一个对象,当不再使用的时候,需要手动调用delete方法来进行销毁。而Java提供了一套完整的垃圾回收机制(gc)。它会自动扫描内存中我们所创建过且不再使用的对象,进行自动销毁。但是gc并不完美,现实中还是会出现内存溢出的情况的,这也从另一方面说明了gc的工作流程是不能被保证的。
关于java的内存回收有几个相关的方法,finalize(),System.gc(),System.runFinalization()以及System.runFinalizersOnExit(true)。
finalize():
finalize方法是定义在Object对象中的:

protected void finalize() throws Throwable { }

该方法只有在gc开始着手清理该对象时才会执行,所以JVM并不是必定会执行该方法的,比如你的程序在退出前都没有释放过该资源,那么该方法就不会执行。所以如果你重写了该方法,并在其中写了一定的操作,那么它是不能被保证一定执行的。

System.gc():
该方法有时被人称作强制调用系统的gc,然而这是不准确的,该方法只是建议gc进行一次回收,然而对于它是否能被执行,这是不受保障的。

System.runFinalization():
该方法是用来强制调用已经失去引用的对象finalize方法。

System.runFinalizersOnExit(boolean value):
该方法用于在程序结束后进行垃圾回收。该方法如今已被废弃,因为其存在安全性问题,因为它可能导致仍在活动的对象调用finalizers,当有线程并发操作这些对象的时候就会出现一些奇怪的行为和死锁。

下面通过一个小例子来加深理解:

package test;
 
 
public class GCTest {
    public static void main(String[] args) {
        //当运行时没传入参数提醒传入参数,before/after/others
        if (args.length == 0) {
            System.err.println("Usage: \n" + "java Garbage before\n or:\n"
                    + "java Garbage after");
            return;
        }
        
        //当finishCreate标记不为true时,持续创建Demo对象和String对象,String对象是为了加大内存消耗,来吸引gc的关注
        while (!Demo.finishCreate) {
                new Demo();
                new String("To take up space");
                
        }
        System.out.println("After all Demos have been created:\n"
                + "total created = " + Demo.createdNum + ", total finalized = "
                + Demo.finalizedNum);
        
        //如果传入的参数为before,则先后执行System.gc()和System.runFinalization();
        if (args[0].equals("before")) {
            System.out.println("gc():");
            System.gc();
            System.out.println("runFinalization():");
            System.runFinalization();
        }
        System.out.println("bye!");
        //如果传入的参数为after,则调用System.runFinalizersOnExit(true),该方法已被废弃,因为存在安全性
        if (args[0].equals("after"))
            System.runFinalizersOnExit(true);
    }
}
 
 
class Demo {
    // 判断当前内中gc是否运行
    static boolean gcrun = false;
    // 用于控制是否继续生成对象的开关
    static boolean finishCreate = false;
    // 用来记录对象创建的数量
    static int createdNum;
    // 用来记录对象被销毁的数量
    static int finalizedNum;
    
    static boolean tempFlag;
    // 用来区分当前对象的标记
    int id;
 
 
    // 无参构造函数
    public Demo() {
        // 每创建一个对象,createNum+1,并将其赋值给当前对象id
        id = ++createdNum;
        if (createdNum == 50) {
            System.out.println("the fiftieth Demo has been created");
        }
    }
 
 
    @Override
    protected void finalize() throws Throwable {
        //当第一次执行finalize的时候,表示gc开始自动销毁对象了
        if (!gcrun) {
            gcrun = true;
            System.out.println("Gabage Collection begins running after "
                    + createdNum + "demo objects have been created");
        }
        //当销毁的对象id>=50时,将finishCreate标记置为true,停止创建更多的对象
        if (id >= 50 && !tempFlag) {
            tempFlag = true;
            finishCreate = true;
            System.out
                    .println("the fiftieth demo begins to finalize and stop creating more demos");
        }
        //没执行一次finalize方法,finalizeNum都加1
        finalizedNum++;
//      System.out.println(finalizedNum+"===="+createdNum);
        //当finalizeNum >= createNum,表示所有对象都被清除
        if (finalizedNum >= createdNum) {
            System.out.println("all gabage have benn collected");
        }
    }
 
 
}

运行上述代码,传入不同的参数,可以进行不同的操作,Eclipse中带参的运行方法为右键Run As > Run Configurations… > Arguments 填入参数:
在这里插入图片描述
下面为几种运行结果:

1.传入参数before运行:
在这里插入图片描述
打开Demo类finalize中的打印语句可以看到如下打印:
在这里插入图片描述
第一种执行的是System.gc()和System.runFinalization()方法,从最后的输出可以看出,并没有完全的销毁对象,程序就结束了,这再一次证明了java垃圾回收机制的不确定性。
2.传入参数after运行:
在这里插入图片描述

打开Demo类finalize中的打印语句可以看到如下打印:
在这里插入图片描述
通过以上打印可以看出,所有的对象都被清理了,但明显感觉到程序的效率变慢了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/790146.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

7plus透明屏有哪些全新的使用体验?

7plus透明屏是指苹果公司推出的iPhone 7 Plus手机配备了透明屏幕的一种特殊版本。透明屏幕是一种新型的显示技术,可以使屏幕看起来透明,让用户感觉手机屏幕上的内容仿佛悬浮在空中一样。 透明屏幕的出现给用户带来了全新的使用体验。 首先,透…

对象存活判断

对象存活判断 在堆里存放着几乎所有的 Java 对象实例,在 GC 执行垃圾回收之前,首先需要区分出内存中哪些是存活对象,哪些是已经死亡的对象。只有被标记为己经死亡的对象,GC 才会在执行垃圾回收时,释放掉其所占用的内存…

微信小程序客服系统-对接消息推送-对接模板订阅消息-嵌入webview客服链接

想要给自己的小程序增加客服系统功能 小程序客服对接导自己的系统等需求,可以参照我开发的客服系统,实现私有化部署搭建对接的微信小程序 小程序消息推送对接 首先登录小程序后台在小程序后台>开发管理>开发设置>服务器域名部分,配置…

基于Java+SpringBoot+vue前后端分离学科竞赛管理系统设计实现

博主介绍:✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专…

Linux中的库

一、库是什么 库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。就是将源代码转化为二进制格式的源代码,相当于进行了加密,别人可以使用库,但是看不到库中的内容。 二、库的分类和优缺点 静态库:是在程…

Shell 排序法 - 改良的插入排序

说明 插入排序法由未排序的后半部前端取出一个值,插入已排序前半部的适当位置,概念简单但速度不快。 排序要加快的基本原则之一,是让后一次的排序进行时,尽量利用前一次排序后的结果,以加快排序的速度,Shel…

云安全攻防(二)之 云原生安全

云原生安全 什么是云原生安全?云原生安全包含两层含义:面向云原生环境的安全和具有云原生特征的安全 面向云原生环境的安全 面向云原生环境的安全的目标是防护云原生环境中的基础设施、编排系统和微服务系统的安全。这类安全机制不一定会具有云原生的…

git恢复删除的分支

1.查看被删除的分支 git remote prune --dry-run origin 被删除的分支是191 2.找到被删除分支的最后一次提交记录的commit SHA值 git reflog 最后一次提交的commit SHA值是3fa7532 3.恢复分支 git checkout -b xiaomeng 3fa7532 4.恢复成功后提交到远端,over&…

[大模型] LLaMA系列大模型调研与整理-llama/alpaca/lora(部分)

文章目录 LLaMA大模型及其衍生模型1. LLaMA2. stanford_alpaca3. ChatDoctor4. alpaca-lora5. Chinese-LLaMA-Alpaca6. BELLE 大模型综述 A Survey of Large Language Models 关键词:大模型,LLaMA,Alpaca,Lora,Belle&a…

git拉取提交代码进行身份验证-输入账号密码以及配置SSH公钥

git初次拉取代码或者提交代码时,需要进行身份验证。验证有两种方式:1、账号密码验证;2、SSH公钥验证。 本文章以gitee为例 账号密码验证 1.首先找到电脑本地项目文件夹,在地址栏中输入cmd回车,打开命令行窗口。 2.输入…

【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(集群功能分析)

探究Redis服务启动的过程机制的技术原理和流程分析的指南(集群功能分析) Redis集群的出现背景提升性能扩展性 Redis集群概述Redis Cluster特性分布Redis Cluster的Failover机制Redis集群节点宕机集群如何判断节点是否挂掉集群进入失败状态的必要条件 Fai…

git实战

git实战 第一章 快速入门 1.1 什么是git git是一个分布式的版本控制软件。 软件,类似于QQ、office、dota等安装到电脑上才能使用的工具。版本控制,类似于毕业论文、写文案、视频剪辑等,需要反复修改和保留原历史数据。分布式 - 文件夹拷贝…

抖音seo短视频矩阵系统源码开发解析---多账号授权管理

本文开发语音使用PHP语言开发,梅雨plum框架自主研发,文末另附开发技巧 抖音SEO短视频矩阵系统源码开发解析是一种基于抖音平台的短视频排名优化技术,通过对抖音算法的分析和抖音用户行为的研究,提供一种基于“流量矩阵”的短视频管…

TCP/IP 五层协议模型

转载大佬文章 我们每天使用互联网,本质上是在传输/接收各种数据,具体如何传输则是按照一系列互联网协议进行的。我们常说的网络七层模型,五层模型,四层模型都是对数据传输过程做了细化的分层。 按照五层模型比较好理解&#xff0c…

Amazon Redshift Serverless – 现已正式推出新功能

去年在 re:Invent 上,我们推出了 Amazon Redshift Serverless 的预览版,这是 Amazon Redshift 的无服务器选项,可让您分析任何规模的数据,而无需管理数据仓库基础设施。您只需要加载和查询数据,并且只需为使用的内容付…

C语言动态内存管理(三)

目录 五、C/C程序的内存开辟1.图解2.关键点 六、柔性数组1.什么是柔性数组2.两种语法形式3.柔性数组的特点4.柔性数组的创建及使用在这个方案中柔性数组的柔性怎么体现出来的? 5.不用柔性数组,实现数组可大可小的思路6.对比 总结 五、C/C程序的内存开辟 1.图解 &a…

上手 SpringBoot

简介 SpringBoot设计的目的是简化 Spring应用的初始搭建以及 开发过程。 SpringBoot概述 parent 继承父pom文件,方便管理依赖的版本。此处涉及maven的使用 作用: 继承parent的形式可以采用引入依赖的形式实现效果 starter(原理是依赖传递) 包含了若…

C语言include学习

#include叫做文件包含命令&#xff0c;用来引入对应的头文件&#xff08;.h文件&#xff09;。 #include 也是C语言预处理命令的一种。 一个简单程序&#xff0c; #include <stdio.h>int main() {printf("hello world\n");return 0; } 使用printf()函数需要…

从虚拟现实到真实现实:沉浸式体验的未来 (ps beta)

首先&#xff0c;您需要创建一个免费的Adobe账户&#xff0c;如果您还没有一个账户的话。您可以在Adobe的注册页面上填写必要的信息来创建一个新账户。 Adobe: Creative, marketing and document management solutions login 创建账号&#xff1a; 编一个google邮箱&#xf…

F5 LTM 知识点和实验 1-BIG-IP 系统介绍

第一章&#xff1a;BIG-IP 系统介绍 基于包转发和全代理架构的区别&#xff08;packet-based vs full proxy architeture&#xff09; 一个网络设备如果是基于包转发的&#xff0c;则他是一个会话流&#xff08;communication stream&#xff09;的中间设备&#xff0c;而不是…