为什么在方法中声明的对象在方法返回之前会受到垃圾回收?

2024-05-15

考虑在方法中声明的对象:

public void foo() {
    final Object obj = new Object();

    // A long run job that consumes tons of memory and 
    // triggers garbage collection
}

obj 会被垃圾回收吗beforefoo() 返回?

UPDATE: 之前我以为obj不会被垃圾回收untilfoo() 返回。

然而,今天我发现自己错了。

我花了几个小时修复一个错误,最后发现问题是由 obj 垃圾收集引起的!

谁能解释为什么会发生这种情况?如果我想要固定 obj 如何实现?

这是有问题的代码。

public class Program
{
    public static void main(String[] args) throws Exception {
        String connectionString = "jdbc:mysql://<whatever>";

        // I find wrap is gc-ed somewhere
        SqlConnection wrap = new SqlConnection(connectionString); 

        Connection con = wrap.currentConnection();
        Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, 
             ResultSet.CONCUR_READ_ONLY);
        stmt.setFetchSize(Integer.MIN_VALUE);

        ResultSet rs = stmt.executeQuery("select instance_id, doc_id from
               crawler_archive.documents");

        while (rs.next()) {
            int instanceID = rs.getInt(1);
            int docID = rs.getInt(2);

            if (docID % 1000 == 0) {
                System.out.println(docID);
            }
        }

        rs.close();
        //wrap.close();
    }
}

Java程序运行后,在崩溃之前会打印以下消息:

161000
161000
********************************
Finalizer CALLED!!
********************************
********************************
Close CALLED!!
********************************
162000
Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: 

这是 SqlConnection 类的代码:

class SqlConnection
{
    private final String connectionString;
    private Connection connection;

    public SqlConnection(String connectionString) {
        this.connectionString = connectionString;
    }

    public synchronized Connection currentConnection() throws SQLException {
        if (this.connection == null || this.connection.isClosed()) {
            this.closeConnection();
            this.connection = DriverManager.getConnection(connectionString);
        }
        return this.connection;
    }

    protected void finalize() throws Throwable {
        try {
            System.out.println("********************************");
            System.out.println("Finalizer CALLED!!");
            System.out.println("********************************");
            this.close();
        } finally {
            super.finalize();
        }
    }

    public void close() {
        System.out.println("********************************");
        System.out.println("Close CALLED!!");
        System.out.println("********************************");
        this.closeConnection();
    }

    protected void closeConnection() {
        if (this.connection != null) {
            try {
                connection.close();
            } catch (Throwable e) {
            } finally {
                this.connection = null;
            }
        }
    }
}

我真的对此感到惊讶,但你是对的。它很容易重现,您不需要担心数据库连接等:

public class GcTest {

    public static void main(String[] args) {
        System.out.println("Starting");

        Object dummy = new GcTest(); // gets GC'd before method exits

        // gets bigger and bigger until heap explodes
        Collection<String> collection = new ArrayList<String>();

        // method never exits normally because of while loop
        while (true) {
            collection.add(new String("test"));
        }
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("Finalizing instance of GcTest");
    }
}

运行:

Starting
Finalizing instance of GcTest
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2760)
    at java.util.Arrays.copyOf(Arrays.java:2734)
    at java.util.ArrayList.ensureCapacity(ArrayList.java:167)
    at java.util.ArrayList.add(ArrayList.java:351)
    at test.GcTest.main(GcTest.java:22)

就像我说的,我简直不敢相信,但无可否认的证据。

不过,这确实有一种反常的意义,虚拟机会发现该对象从未被使用过,因此会删除它。这必须得到规范的允许。

回到问题的代码,你永远不应该依赖finalize()要清理你的连接,你应该always明确地做。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么在方法中声明的对象在方法返回之前会受到垃圾回收? 的相关文章

  • Google 地图查询返回的 JSON 包含像 \x26 这样的编码字符(如何解码?)

    在 Java 应用程序中 我获取 JSON 来自 Google 地图 其中包含以下字符 x26我想将其转换为其原始字符 据我所知 这是一个 UTF 8 表示法 但我不完全确定 在源 JSON 中 可能会出现各种编码字符 例如 x3c div
  • 将链接对象转换为流或集合

    我想迭代堆栈跟踪 堆栈跟踪由可抛出对象组成 其 getCause 返回下一个可抛出对象 最后一次调用 getCause 返回 null 示例 a gt b gt null 我尝试使用 Stream iterable 这会导致 NullPoi
  • Java 创建浮雕(红/蓝图像)

    我正在编写一个 Java 游戏引擎 http victoryengine org http victoryengine org 并且我一直在尝试生成具有深度的 3D 图像 您可以使用那些红色 蓝色眼镜看到 我正在使用 Java2D 进行图形
  • 通过 InjectMocks Spy 注入对象

    我需要对一个类运行一系列单元测试 该类具有 Autowired Logger 实现 实现的基本思想是 Mock Logger logger InjectMocks TestedClass tested 但我想保存日志输出功能 Mockito
  • 如何对 IntStream 进行逆序排序

    我正在使用 txt 文件读取数字BufferedReader 我想颠倒该流中元素的顺序 以便在收集它们时 它们将从最高到最低排列 我不想在构建数组后进行排序 因为我不知道其中可能有多少元素 我只需要最高的 N 个元素 in new Buff
  • 方法断点可能会大大减慢调试速度

    每当向方法声明行添加断点 在 Intellij IDEA 或 Android Studio 中 时 都会出现一个弹出窗口 方法断点可能会大大减慢调试速度 为什么会这样戏剧性地减慢调试速度 是我的问题吗 将断点放在函数的第一行有什么不同 Th
  • PropertySources 中各种源的优先级

    Spring引入了新的注释 PropertySources对于所有标记为的类 Configuration since 4 0 需要不同的 PropertySource作为论证 PropertySources PropertySource c
  • Java 变量的作用域

    我不明白为什么这段代码的输出是10 package uno public class A int x 10 A int x 12 new B public static void main String args int x 11 new
  • 场景生成器删除 fxml 文件中的导入

    我使用场景构建器 Gluon Scene Builder JavaFX Scene Builder 8 1 1 来创建应用程序的 UI 并使用 Eclipse 开发 JavaFX 现在 每次我在场景生成器中保存某些内容时 它都会从 fxml
  • 如何将 XMP XML 块序列化为现有的 JPEG 图像?

    我有许多 JPEG 图像 其中包含损坏的 XMP XML 块 我可以轻松修复这些块 但我不确定如何将 固定 数据写回图像文件 我目前正在使用 JAVA 但我愿意接受任何能让这项任务变得容易的事情 这是目标关于 XMP XML 的另一个问题
  • cucumber-junit-platform-engine 中的功能文件发现

    In cucumber junit我使用的库 CucumberOptions定义功能文件位置 package com mycompany cucumber import cucumber api CucumberOptions import
  • 使用 java 按电子邮件发送日历邀请

    我正在尝试使用 java 发送每封电子邮件的日历邀请 收件人收到电子邮件 但不会显示接受或拒绝的邀请 而是将该事件自动添加到他的日历中 我正在使用 ical4j jar 构建活动 邀请 private Calendar getInvite
  • 想要开发像 Facebook 这样的网站 - 处理数百万个请求 - 高性能 [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我想用 Java 开发一个像 Fac
  • 如何在java中使jpeg无损?

    有没有人可以告诉我如何使用编写 jpeg 文件losslessjava中的压缩 我使用下面的代码读取字节来编辑字节 WritableRaster raster image getRaster DataBufferByte buffer Da
  • 具有多种值类型的 Java 枚举

    基本上我所做的是为国家编写一个枚举 我希望不仅能够像国家一样访问它们 而且还能够访问它们的缩写以及它们是否是原始殖民地 public enum States MASSACHUSETTS Massachusetts MA true MICHI
  • tomcat 过滤所有 web 应用程序

    问题 我想对所有网络应用程序进行过滤 我创建了一个过滤器来监视对 apache tomcat 服务器的请求 举例来说 它称为 MyFilter 我在 netbeans 中创建了它 它创建了 2 个独立的目录 webpages contain
  • Spring Boot MSSQL Kerberos 身份验证

    目前在我的春季靴子中application properties文件中 我指定以下行来连接到 MSSql 服务器 spring datasource url jdbc sqlserver localhost databaseName spr
  • Java 推断泛型类型

    我正在寻找类似的推断捕获泛型类型的概念 类似于以下方法片段 但不是捕获泛型类型的类 public
  • java中如何找到class文件的包

    我正在编写一个使用 class 文件的 java 程序 我希望能够读取文件系统上的 class 文件 使用 InputStream 并确定它所在的包 该 class 文件可能不在一个好的包目录结构中 它可能位于某个随机位置 我怎样才能做到这
  • 使用 eclipse IDE 配置 angularjs

    我想开始使用 AngularJs 和 Java Spring 进行开发 我使用 Eclipse 作为 IDE 我想配置我的 Eclipse 以使这些框架无缝工作 我知道我可能要求太多 但相信我 我已经做了很多研究 你们是我最后的选择 任何帮

随机推荐

  • 调试器异常错误和内存超调

    我尝试运行以下代码 但它显示有关内存地址的错误 并显示一条消息 循环后 n 可能未定义 请看一看 var n max integer n integer r R1 f h0 Array of Real const h 0 00889 nip
  • 使用 mosca MQTT 的请求响应模式

    有没有办法使用 mosca MQTT 实现请求响应模式 以 检查客户端的回复 如果在预期时间内未收到预期回复 则重新发布 我相信这在 Mqtt 5 中是可能的 但截至目前 我必须使用 QoS 1 的 Mosca 代理 支持直到 Mqtt 3
  • 错误 11 秒后等待 Protractor 与页面同步超时

    我的量角器测试有问题 我的角度应用程序使用 timeout 不断从服务器轮询某些内容 不幸的是 当我运行测试时 这会导致以下错误消息 There was a webdriver error Error Timed out waiting f
  • Javascript 放大/缩小到鼠标 x/y 坐标

    我设法让鼠标拖动来滚动div 但是用鼠标放大 缩小不完整 它有效 但我希望鼠标指针将图像保持在该位置并同时缩放它 如下所示 我需要使用scrollBy 将滚动返回到缩放之前的上一点 有人知道该怎么做吗 这是某人制作的小提琴https jsf
  • 如何在 Android 中启用高速蓝牙(3.0+HS 或 4.0)?

    所以我在两部蓝牙 4 0 Android 手机上有一个 BT 客户端和一个服务器应用程序 服务器等待连接通过 BluetoothServerSocket serverSocket mBluetoothAdapter listenUsingR
  • Python 中的错误? threading.Thread.start() 并不总是返回

    我有一个很小的 Python 脚本 在我看来 threading Thread start 表现出意外 因为它不会立即返回 在线程内我想调用一个方法boost python基于对象 不会立即返回 为此 我将对象 方法包装如下 import
  • 如何使用 bash 显示具有两个子文件夹的文件夹?

    我通过 Cygwin 使用 bash 我有一个大文件夹 a 有很多子文件夹 b 这些子文件夹各有一个或两个子文件夹 c 我想找到所有有两个子文件夹 c 的子文件夹 b 并输出它们 结构如下 a b1 c1 b2 c1 c2 b3 c1 c2
  • 用作 ServiceStack 的 IoC 时在 autofac 中配置生命周期范围

    我目前正在使用 AutoFac 作为我们的 ServiceStack Web 服务应用程序的 DI 容器 我能够配置接线和所有内容 但在阅读了有关范围的部分后 我不知道在注册我的组件时最好使用哪个范围 在我们的特定情况下 我认为 PerHt
  • 如何在禁用的 HTML 按钮上呈现工具提示

    我有一个 HTML 按钮 我尝试根据按钮的 标题 属性在其上渲染工具提示 但它没有渲染 主要是因为它被禁用了 然后 我尝试将按钮包装在跨度中并设置跨度的 标题 属性 将鼠标悬停在包含在跨度中的按钮上仍然没有效果 工具提示将呈现在不属于按钮标
  • 如何从 iOS 应用程序检测不安全的 wifi 网络

    我想检测我的应用程序中是否存在不安全的 wifi 网络 是否有任何公共 iOS API 可以实现相同的目的 没有记录的 API 可以获取该信息 如果您的应用程序需要通过网络发送和接收敏感数据 您通常应该假设没有安全连接
  • 属性中的角度表达式

    我有一个使用 Angular 的页面 其中我从引导程序实现了弹出窗口 img class state msg 数据内容无法正确呈现 它按字面意思返回 item status message 而不是 message 的值 角度在 数据 属性中
  • Jquery POST 获取建议列表

    我有下一个代码 它运行良好 问题是当用户写完单词时 脚本不断创建后调用并不断更改建议列表 我想做一些事情 如果用户继续写一个单词 脚本会停止所有的 post 调用 只执行最后一个 inputString keydown function l
  • 用数字 1-1000 填充 Postgres 数据库?

    我是 pgAdmin3 的新手 我想用数字 1 1000 填充 pgAdmin3 中的数据库 我该怎么做呢 目前 我创建了一个名为 MyDatabase 的数据库 其中没有任何内容 每行应与其数值相对应 第 1 行应包含 1 第 2 行应包
  • JSF 中基于两个组件的组合的验证/转换

    我正在开发一个 JSF Web 应用程序 我需要使用周期性作为数据结构 以下是我使用的 Java 类 public class Periodicity implements Serializable private Integer valu
  • MySQL 帮助:如何查找客户的所有订单,直到价格 <= 20 且状态='未付款'

    我认为通过提供以下示例可以更好地理解我的问题 我有一个包含以下数据的表 orderid Price username paymentstatus 1 10 john unpaid 2 10 john unpaid 4 10 john unp
  • 如何在安装过程中运行“.bat”文件?

    在安装项目中 诸如 exe dll js vbs 之类的可执行文件是可以接受的 但无法运行 bat自定义操作中的文件 问题是如何运行 bat安装过程中的文件 好吧 经过大量搜索和反复试验 我解决了这个问题 我不确定这是否是最好的方法 但它确
  • ORACLE:未找到数据——但数据存在

    调试包过程 当实际上有数据时却找不到数据 仅测试 SELECT SELECT trim trailing from GL SECURITY as DUMMY FROM b2k user b2k WHERE sms username FUCH
  • 面向服务的架构 - AMQP 或 HTTP

    一点背景 非常大的整体 Django 应用程序 所有组件都使用相同的数据库 我们需要分离服务 以便我们可以独立升级系统的某些部分而不影响其余部分 我们使用 RabbitMQ 作为 Celery 的代理 现在我们有两个选择 使用 REST 接
  • 在 Yesod 生态系统中,对某些文本进行 urlencode 的最佳方式是什么?

    我想对一些文本进行 url 编码 例如 用 20 替换每个空格等 我找到了 HTTP Network HTTP Base urlEncode 并且可以使用它 但我想知道是否还有其他通常在 Yesod 生态系统中使用的东西 不幸的是 由于 U
  • 为什么在方法中声明的对象在方法返回之前会受到垃圾回收?

    考虑在方法中声明的对象 public void foo final Object obj new Object A long run job that consumes tons of memory and triggers garbage