前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Fortify Audit Workbench 笔记 Unreleased Resource: Database( 未释放资源:数据库)

Fortify Audit Workbench 笔记 Unreleased Resource: Database( 未释放资源:数据库)

作者头像
用户1637609
发布2020-03-17 18:22:01
1.6K0
发布2020-03-17 18:22:01
举报
文章被收录于专栏:马洪彪马洪彪

Unreleased Resource: Database 未释放资源:数据库

Abstract

程序可能无法成功释放某一项系统资源。

Explanation

程序可能无法成功释放某一项系统资源。 资源泄露至少有两种常见的原因: - 错误状况及其他异常情况。 - 未明确程序的哪一部份负责释放资源。 大部分 Unreleased Resource 问题只会导致一般的软件可靠性问题, 但如果攻击者能够故意触发资源泄漏,该攻击者就有可能通过耗尽资源池的方式发起 denial of service 攻 击。 例 1: 下面的方法绝不会关闭它所打开的文件句柄。 FileInputStream 中的 finalize() 方法最终会调用 close(),但无法保证它调用 finalize() 方法的时间。 在繁忙的环境中,这会导致 JVM 用尽它所有的文件句柄。

代码语言:javascript
复制
private void processFile(String fName) throws FileNotFoundException,
IOException
{
FileInputStream fis = new FileInputStream(fName);
int sz;
byte[] byteArray = new byte[BLOCK_SIZE];
while ((sz = fis.read(byteArray)) != -1) {
processBytes(byteArray, sz);
}
}

例 2: 在正常条件下,以下代码会执行数据库查询指令,处理数据库返回的结果,并关闭已分配的指令对象。 但如果在执行 SQL 或是处理结果时发生异常,指令对象将不会关闭。 如果这种情况频繁出现,数据库将用完所有可用的指针,且不能再执行任何 SQL 查询。

代码语言:javascript
复制
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(CXN_SQL);
harvestResults(rs);
stmt.close();

Recommendation

1.绝不要依赖 finalize() 回收资源。 为了使对象的 Finalize() 方法能被调用,垃圾收集器必须确认对象符合垃圾回收的条件。 但是垃圾收集器只有在 JVM 内存过小时才会使用。因此,无法保证何时能够调用该对象的 finalize() 方法。 垃圾收集器最终运行时,可能出现这样的情况,即在短时间内回收大量的资源,这种情况会导致“突发”性能,并降低总体系统通过量。 随着系统负载的增加,这种影响会越来越明显。 最后, 如果某一资源回收操作被挂起(例如该操作需要通过网络访问数据库),那么执行 finalize() 方法的线程也将被挂起。 2. 在 finally 代码段中释放资源。 例 2 中的代码可按以下方式改写:

代码语言:javascript
复制
public void execCxnSql(Connection conn) {
    Statement stmt;
    try {
        stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery(CXN_SQL);
        ...
    }
    finally {
        if (stmt != null) {
            safeClose(stmt);
        }
    }
}
public static void safeClose(Statement stmt) {
    if (stmt != null) {
        try {
            stmt.close();
        } catch (SQLException e) {
            log(e);
        }
    }
}

以上方案使用了一个助手函数,用以记录在尝试关闭指令时可能产生的异常。 该助手函数大约会在需要关闭指令时重新使用。 同样, execCxnSql 方法不会将 stmt 对象预置为空。 而是进行检查,以确保调用safeClose() 之前, stmt 不是 null。 如果没有检查 null, Java 编译器会报告 stmt 可能没有进行初始化。 编译器做出这一判断源于 Java 可以检测未初始化的变量。 如果用一种更加复杂的方法将 stmt 初始化为 null,那么 Java 编译器就无法检测 stmt 是否已被初始化。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-03-14 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Abstract
  • Explanation
  • Recommendation
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档