Bug: Call to method of static java.text.DateFormat
Pattern id: STCAL_INVOKE_ON_STATIC_DATE_FORMAT_INSTANCE, type: STCAL, category: MT_CORRECTNESS

As
the JavaDoc states, DateFormats are inherently unsafe for multithreaded
use. The detector has found a call to an instance of DateFormat that
has been obtained via a static field. This looks suspicous.

For more information on this see Sun Bug #6231579 and Sun Bug #6178997.

上面的英文解释其实应该说得比较清楚,在Java文档中,已经明确说明了DateFormats 是非线程安全的,而在SimpleDateFormat的Jdk 的Source文件中,我们也找到这么一段注释,说明它不是线程安全的。

Date formats are not synchronized.
* It is recommended to create separate format instances for each thread.
* If multiple threads access a format concurrently, it must be synchronized

在Sun自己的网站上。在sun的bug database中,Sun Bug #6231579Sun Bug #6178997都可以印证这个问题。

导致SimpleDateFormat出现多线程安全问题的原因,是因为:SimpleDateFormat处理复杂,Jdk的实现中使用了成员变量来传递参数,这就造成在多线程的时候会出现错误。

而Findbugs所说的“Call to static DateFormat”,其实就是一些人:为了渐少new 的次数而把SimpleDateFormat做成成员或者静态成员,上面已经说了,这样做是不安全的。

其实,出现这种问题的代码一般都长得差不多,典型的代码示例如下:

public class Test{
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
public void method1(){
dateFormat.format(new Date());
}
public void method2(){
dateFormat.format(new Date());
}
)

再给个详细例子说明问题,看下面代码:

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map; public class Test{
private SimpleDateFormat dateFormat ;
public static void main(String[] args) {
SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd");
Date today = new Date();
Date tomorrow = new Date(today.getTime()+1000*60*60*24);
System.out.println(today); // 今天是2010-01-11
System.out.println(tomorrow); // 明天是2010-01-11
Thread thread1 = new Thread(new Thread1(dateFormat,today));
thread1.start();
Thread thread2 = new Thread(new Thread2(dateFormat,tomorrow));
thread2.start();
} }
class Thread1 implements Runnable{
private SimpleDateFormat dateFormat;
private Date date;
public Thread1(SimpleDateFormat dateFormat,Date date){
this.dateFormat = dateFormat;
this.date = date;
}
public void run() {
for(;;){// 一直循环到出问题为止吧。
String strDate = dateFormat.format(date);
// 如果不等于2010-01-11,证明出现线程安全问题了!!!!
if(!"2010-01-11".equals(strDate)){
System.err.println("today="+strDate);
System.exit(0);
}
}
}
}
class Thread2 implements Runnable{
private SimpleDateFormat dateFormat;
private Date date;
public Thread2(SimpleDateFormat dateFormat,Date date){
this.dateFormat = dateFormat;
this.date = date;
}
public void run() {
for(;;){
String strDate = dateFormat.format(date);
if(!"2010-01-12".equals(strDate)){
System.err.println("tomorrow="+strDate);
System.exit(0);
}
}
}
}

运行的结果如下:

Mon Jan 11 11:30:36 CST 2010
Tue Jan 12 11:30:36 CST 2010
tomorrow=2010-01-11

终于看到问题了,tomorrow=2010-01-11,错得很明显了。其实要避免这个问题方法很简单,不使用SimpleDateFormat,或者不使用成员变量/静态成员变量的SimpleDateFormat对象即可。

今天解决了一个findbug的错误:

Call to method of static java.text.DateFormat in com.pbn.oss.resource.template.input.ws.service.InputTemplateWSServiceImpl.formatDate(Date)

As the JavaDoc states, DateFormats are inherently unsafe for
multithreaded use. The detector has found a call to an instance of
DateFormat that has been obtained via a static field. This looks
suspicous.

初始代码如下:

  1. private static final SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
  2. format.format(new Date());
  1. 同一个format 多次调用会导致线性不安全,

可以改为:

    1. private static final String COMMON_DATE = "dd/MM/yyyy";
    2. SimpleDateFormat format = new SimpleDateFormat(COMMON_DATE);
    3. format.format(new Date());

参考资料

【1】.《使用SimpleDateFormat必须注意的问题

Call to static DateFormat的更多相关文章

  1. FindBug:Call to static DateFormat

    今天在重构代码的过程中碰到了一个问题.使用SimpleDateFormat的问题. 本人今天写了一个类,主要是提供很多静态的方法由其他接口调用,过程中多个方法使用到了日期的格式化,所以我讲Simple ...

  2. DateFormat 中间加别的字符

    private static DateFormat dateTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");

  3. Java Calendar,Date,DateFormat,TimeZone,Locale等时间相关内容的认知和使用(4) DateFormat

    本章主要介绍DateFormat. DateFormat 介绍 DateFormat 的作用是 格式化并解析“日期/时间”.实际上,它是Date的格式化工具,它能帮助我们格式化Date,进而将Date ...

  4. 详解Java中格式化日期的DateFormat与SimpleDateFormat类

    DateFormat其本身是一个抽象类,SimpleDateFormat 类是DateFormat类的子类,一般情况下来讲DateFormat类很少会直接使用,而都使用SimpleDateFormat ...

  5. Date、Calendar、DateFormat、SimpleDateFormat、Timer、TimerTask类

    类 Date 在 JDK 1.1 之前,类 Date 有两个其他的函数.它允许把日期解释为年.月.日.小时.分钟和秒值. 它也允许格式化和解析日期字符串.不过,这些函数的 API 不易于实现国际化.从 ...

  6. java中Dateformat类的详细使用(详解)

    DateFormat其本身是一个抽象类,SimpleDateFormat 类是DateFormat类的子类,一般情况下来讲DateFormat类很少会直接使用,而都使用SimpleDateFormat ...

  7. Java—时间的原点 计算时间所使用的 Date类/DateFormat类/Calendar类

    Date类 类 Date 表示特定的瞬间,精确到毫秒. 毫秒概念:1000毫秒=1秒 毫秒的0点: System.currentTimeMillis()  返回值long类型参数 用于获取当前日期的毫 ...

  8. 从接口、抽象类到工厂模式再到JVM来总结一些问题

    俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习! 涉及到的知识点总结如下: 为什么使用接口? 接口和抽象类的区别 简单工厂模式总结 Java中new和newInstance的区别 J ...

  9. Java中一些常用的方法

    1.计算程序运行时常 long start = System.currentTimeMillis(); … … … long end = System.currentTimeMillis(); Sys ...

随机推荐

  1. ubifs笔记

    第1章 UBIFS UBIFS不是工作在块在设备之上,所以UBIFS不能用于MMC之类的设备. 与传统的flash文件不同,UBIFS不是工作是块设备之上.传统的flash文件系统(如Jffs2)工作 ...

  2. 为什么输入shutdown -h -t会报错:command not fount

    如果是直接用普通用户($)的身份进行输入[user@localhost ~]$ shutdown -h -t 是不能执行,因为普通用户没有关闭机器的权限. 然而直接使用[user@localhost ...

  3. “/”和“\\”和feof();

    filename=c:/test/abc.text filename=c:\\test\\abc.test "\\"为转义字符: feof();函数检测文件是否已经到达末尾(EOF ...

  4. 转: 初识Agile/CMMI/Scrum

    转:http://www.cnblogs.com/maxwell/p/5093917.html 一.背景介绍 在朋友(aehyok)的建议下,初步去了解Visual Studio Online,简称V ...

  5. Java Applet 基础

    Java Applet 基础 Applet 是一种 Java 程序.它一般运行在支持 Java 的 Web 浏览器内.因为它有完整的 Java API支持,所以Applet 是一个全功能的 Java ...

  6. 【BIEE】07_调整BIEE柱子的显示顺序

    现在有报表如下: 但是我们觉得这种显示不好看,想把非优秀员工的柱子放在前边显示,那么如何调整呢? 调整步骤: [编辑分析] 我们将此处条形图下的两个标签顺序重新调整一下 从上图可以看出,效果明显!

  7. mongo 增

    mongodb存储的是文档,文档是json格式的对象,我们的增删改查,都要传输json对象 json是一个对象,js里有数组这个概念,只需要把多个对象放到一个数组里,即可 use test //首先选 ...

  8. Java 分页之最简单的算法

    分页实现有很多方式,如jQuery自带框架pagination或在java封装一个类pager等.   下写一个简单易懂的分页算法   逻辑:   // 步骤1:设置每页页数大小 long pageS ...

  9. 【原创】分布式之数据库和缓存双写一致性方案解析(三) 前端面试送命题(二)-callback,promise,generator,async-await JS的进阶技巧 前端面试送命题(一)-JS三座大山 Nodejs的运行原理-科普篇 优化设计提高sql类数据库的性能 简单理解token机制

    [原创]分布式之数据库和缓存双写一致性方案解析(三)   正文 博主本来觉得,<分布式之数据库和缓存双写一致性方案解析>,一文已经十分清晰.然而这一两天,有人在微信上私聊我,觉得应该要采用 ...

  10. ASP.NET CORE RAZOR :将文件上传至 ASP.NET Core 中的 Razor 页面

    本部分演示使用 Razor 页面上传文件. 本教程中的 Razor 页面 Movie 示例应用使用简单的模型绑定上传文件,非常适合上传小型文件. 有关流式传输大文件的信息,请参阅通过流式传输上传大文件 ...