与这个检测器相关的是 Confusing Method Names 检测器,它是对名称类似 hashcode() 和 tostring() 的方法触发的,对于下面这些类也会触发这个检测器:具有一些只在名称大小写方面存在差异的方法,或者其方法与超类构造函数的名称相同。虽然根据该语言的规范,这些方法名称是合法的,但是它们可能不是您想要的。类似地,如果域 serialVersionUID 不是 final ,不是 long ,也不是 static ,就会触发 Serialization 检测器。
Finalizer 不是朋友
在“ Garbage collection and performance”中,我尽力阻止使用 finalizer。Finalizer 需要牺牲很多性能,并且它们不能(甚至完全不能)保证在预计的时间段运行。仍然有些时候需要使用 finalizer,而这样做的过程中可能产生很多错误。如果必须使用 finalizer,通常应该如清单 2 所示来组织它:
清单 2. 正确的 finalizer 定义
protected void finalize() { try { doStuff(); } finally { super.finalize(); } }
FindBugs 检测很多有问题的 finalizer 构造,如:
空的 finalizer(它抵消超类 finalizer 的作用)。 不实现任何功能的 finalizer(它只调用 super.finalize() ,但是这对运行时优化可能造成一些损害)。 显式的 finalizer 调用(从用户代码中调用 finalize() )。 公共 finalizer(finalizer 应该声明为 protected )。 没有调用 super.finalize() 的 finalizer。这些 bug 模式的例子如清单 3 所示:
清单 3. 常见的 finalizer 错误
// negates effect of superclass finalizer protected void finalize() { } // fails to call superclass finalize method protected void finalize() { doSomething(); } // useless (or worse) finalizer protected void finalize() { super.finalize(); } // public finalizer public void finalize() { try { doSomething(); } finally { super.finalize() } }
在“ Garbage collection and performance”中,还讲到另一种垃圾收集危险:显式地调用 System.gc() 。这种显式的调用几乎完全是“帮助”或“欺骗”来机收集器的误导尝试,并且它们最终经常损害性能,而不是对其有利。FindBugs 可以检测显式的 System.gc() 调用,并标记它们(在 Sun JVM 上,还可以使用 -XX:+DisableExplicitGC 启动选项,禁用显式的垃圾收集)。
安全构造技术
在“ Java 理论和实践:安全构造技术”中,我展示了允许对象的引用逃避其构造函数如何导致一些严重的问题。从那时起,允许 this 引用逃避构造的风险变得越来越严重。如果允许对象的引用逃避其构造函数,新的 Java Memory Model(如 JSR 133 所指定,并由 JDK 1.5 实现的)抵消了所有初始化安全保证。
对象的引用可以以几种方式逃避它的构造函数,直接和简接都可以。绝对不可以将 this 引用保存在静态变量或数据结构中,但是有更微妙的方式允许引用逃避构造,如公布对非静态内部类的引用,或者从构造函数中启动一个线程(这几乎总是公布对新线程的引用)。FindBugs 有一个检测器,用于寻找从构造函数启动线程的实例,虽然目前它不能检测所有这些危险,但是未来的版本很可能包括用于其他初始化安全模式的检测器。
为内存模型带来好处
文章来源于领测软件测试网 https://www.ltesting.net/