【问题标题】:Tomcat hangs calling TimeZoneTomcat 挂起调用 TimeZone
【发布时间】:2012-08-26 07:01:59
【问题描述】:

我遇到了导致生产下降的问题。在 AWS/Ubuntu/Tomcat 堆栈中,正在运行的 Tomcat 的 CPU 跳到 100%,当我得到一个线程转储时,这一段代码总是在同一个地方被阻塞。 (所有其他人都被锁定并等待。)

"TP-Processor6" daemon prio=10 tid=0x0000000041ec2800 nid=0x41c4 runnable [0x00007f70194b5000]
  java.lang.Thread.State: RUNNABLE
    at sun.util.calendar.ZoneInfo.getTransitionIndex(ZoneInfo.java:322)
    at sun.util.calendar.ZoneInfo.getOffsets(ZoneInfo.java:248)
    at sun.util.calendar.ZoneInfo.getOffsets(ZoneInfo.java:225)
    at java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2024)
    at java.util.GregorianCalendar.computeFields(GregorianCalendar.java:1996)
    at java.util.Calendar.setTimeInMillis(Calendar.java:1109)
    at java.util.GregorianCalendar.<init>(GregorianCalendar.java:576)
    at java.util.Calendar.createCalendar(Calendar.java:1011)
    at java.util.Calendar.getInstance(Calendar.java:948)
    at com.xxx.core.util.DateUtil.modifyDate(DateUtil.java:385)
    at com.xxx.core.util.DateUtil.getDayDate(DateUtil.java:563)
    at com.xxx.core.util.DateUtil.getDayDate(DateUtil.java:573)
    at com.xxx.core.util.DateUtil.getDayDate(DateUtil.java:569)
    at com.xxx.core.util.DateUtil.splitByDays(DateUtil.java:496)
    at com.xxx.core.util.DateUtil.splitDateIntervalByIntervals(DateUtil.java:474)
    at com.xxx.core.util.DateUtil.splitDateIntervalByIntervals(DateUtil.java:436)

【问题讨论】:

  • 您是否遇到堆栈溢出错误?
  • 操作系统设置有问题,你在其他机器上试过吗?
  • 您是提供时区,还是获取默认时区?
  • ubuntu@ip-10-2-118-175:~$ java -version java version "1.6.0_24" Java(TM) SE Runtime Environment (build 1.6.0_24-b07) Java HotSpot( TM) 64 位服务器 VM(内部版本 19.1-b02,混合模式)
  • 调用 Calendar.getInstance 的代码是这样的: Calendar calendar = Calendar.getInstance();日历.setTime(日期); calendar.setTimeZone(TimeZone.getDefault());

标签: java timezone timezone-offset


【解决方案1】:

围绕事情进行一些更好的日志记录,以了解这里发生了什么。

确保您的实例指定了正确的编码和区域设置——系统、tomcat 容器、应用程序。以格林威治标准时间为标准并尝试:

Calendar.getInstance ("GMT-0", Locale.US); // verify inputs

如果您正在获取日历的实例,为什么要明确地重新设置日期?为什么不直接创建一个新日历?然后您将实例化一个新日历:

Calendar cal = new Calendar (TimeZone zone, Locale aLocale); // new 
cal.setTimeZone("GMT-0"); 
cal.setTimeInMillis(System.currentTimeMillis ()); 

Calendar 和 Date 对象在 Java 中相对具有可塑性,因此您可以更改它们的功能。我猜想环境变量或容器中可能有一些设置不正确,例如本地或编码与日历实例尝试的内容冲突。尝试明确指定所有内容。

这是我最好的直觉。

【讨论】:

  • 从其他地方的帖子中,我添加了 joda-time(我非常喜欢,顺便说一句),但这让我发现问题不是我想的那样。尽管我确实查看了 12-15 个不同的线程转储,它们都显示了相同的东西——上面的方法——它实际上是在一个紧密的循环中旋转,并且线程总是意外地在同一个地方。那个方法的执行时间,即 getTransitionIndex() 调用,相对于所有其他方法来说必须很长,以至于每次我查看线程在做什么时,它总是在同一个地方。哦!
  • Joda Time 很棒,请注意它的局限性。我了解 Joda Time 仅限于毫秒精度,而某些 DB 则喜欢微秒或更高的精度。另外,如果我记得的话,我认为它不能很好地处理闰秒。 stackoverflow.com/questions/375544/…
  • 哦,很高兴您找到了问题的根源。我希望日志记录有所帮助。 :)
猜你喜欢
  • 1970-01-01
  • 2022-01-17
  • 2012-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多