zoukankan      html  css  js  c++  java
  • 说说 bytex 的 extension (2) closeablecheck 插件

    closeable-check 是 byteX 里的一个插件。可以用来检测代码里是 Closeable 的局部变量对象未关闭的问题,Closeable 是 java 里的一个接口,表示该资源使用之后需要及时 close 以节约资源占用。如果没有正确 close 有可能会导致问题。例如 File 文件,如果使用后没有及时 close 的话,会导致文件一直被进程打开,可能会影响操作系统分配给进程的资源管理。

    closeable-check 这个插件检测 Closeable 对象是否已经关闭的逻辑是比较复杂的,其中需要使用 asm 的字节码控制流分析,来分析一个 Closeable 是否可能没有明确关闭。其中分析字节码控制流的方式可以有很多功能扩展,所以今天想简单介绍下。

    在这之前,先简单说一下 asm 分析方法的控制流的过程

    asm 分析控制流

    • 笔者认为需要先简单知道一下这些内容,可以更好理解
      • 字节码指令中有跳转指令,类似 JUMP 。
      • java 方法编译字节码的规则,即 java 方法会如何被解析编译成字节码指令。

    首先这个分析操作的对象是某个方法,该方法可以认为是一个字节码指令数组。即 分析 的输入是

    • 字节码指令数组

    这个分析操作得到的结果是每一个字节码指令可以跳转到的位置(字节码指令中有跳转指令,这类指令可以使得实际执行的时候程序计数器不去执行接下来相邻的指令,而去执行指定的某个指令)。所以 分析 的输出是

    • 字节码指令数组之间的可跳转连接。

    而借助这个得到的控制流信息,我们就可以对一个对象可能的执行流程进行遍历和处理了。closeable-check 所做的就是

    1. 找到所有的 Closeable 对象
    2. 依次对每个 Closeable 对象进行处理,判断其所有可能的执行分支是否有未关闭的情况。

    简单地说下 closeable-check 的实现思路

    类似那个小品里的说法,”把大象放到冰箱需要几步?“,实际上,”检测 Closeable 未关闭需要几步“ 是一样的回答。

    1. 找到所有的 Closeable
    2. 对每个 Closeable 可能进行的代码路径进行遍历,判断其是否关闭了。如果某个路径未关闭,那么提出报告。

    实际的 closeable-check 的实现略有差别,其是这样的:

    1. 找到方法里所有的字节码指令的路径
    2. 遍历每一个路径,分析其中对 Closeable 对象的打开和关闭操作,看是否是一一匹配的,如果只有打开而没有关闭的话,就认为是未关闭的,提出报告。

    其中的第一步 “找到方法里所有的字节码指令的路径” , 借助上面提到的字节码控制流,是可以实现的。

    第一步之后,我们得到了一个路径数组,之后要做的事情是遍历每一个路径,判断其中是否有 Closeable 对象未关闭。

    这一步中,因为一个代码路径是由连续的字节码指令组成的,每个代码路径其实是单向的代码执行。主要的问题有两个:

    • 该代码路径中的代码处理,哪些类型的指令代表了”打开一个 Closeable“,哪些类型的指令代表了”关闭某个 Closeable“
    • 一个路径里面出现的多个 Closeable ,应该如何进行对应?即区分执行 close 的时候是哪个 Closeable 对象被 close 了。

    其中 哪些类型的指令代表打开,哪些类型代表关闭 这个问题,是现在的字节码指令的功能决定的。打开 Closeable 的指令有 ”使用 new 新建一个对象“ 、”某个方法返回了一个 Closeable 对象“。而关闭 Closeable 的指令有 ”对某个 Closeable 对象调用其 close 方法“。

    第二个问题,多个 Closeable 对象如何对应? 因为 closeable-check 只检测方法的局部变量,而字节码指令里局部变量是具有唯一的标识的,通过该标识可以进行分别。

    部分启发

    • 使用 asm 可以进行方法字节码的处理,获取方法的控制流,这对于一些比较高级的字节码相关的分析处理是很有用的。但是写起来确实复杂,对字节码需要有很熟悉的了解才行。
  • 相关阅读:
    日期插件,年月,年月日,时分,年月时分
    <context:annotation-config/>
    Autowired注解
    context:component-scan 注解的扫描
    Servlet 是什么 有哪些类
    spring RestTemplate 出现 NoHttpResponseException 和 ConnectionTimeoutException
    java 动态加载groovy 脚本
    java 如何实现文件变动的监听
    英文文档地址
    Resource ResourceLoader
  • 原文地址:https://www.cnblogs.com/wkmcyz/p/15734338.html
Copyright © 2011-2022 走看看