Uploaded image for project: 'Commons Lang'
  1. Commons Lang
  2. LANG-1641

Over Stack Issue

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Major
    • Resolution: Unresolved
    • 3.7
    • None
    • lang.time.*
    • None

    Description

      //this is the demo
      package com.wcs233;
      
      import java.util.Date;
      import java.util.TimeZone;
      
      import org.apache.commons.lang3.time.DateFormatUtils;
      import org.apache.commons.lang3.time.FastTimeZone;
      
      public class GmtTimeZoneIssue {
      
          public static void main(String[] args) {
              final String timeZoneString = "GMT+7:00";
              final String ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZZ";
      
              for (int i = 0; i < 100; i++) {
                  Date date = new Date();
      
                  TimeZone timeZone = FastTimeZone.getTimeZone(timeZoneString);
      
                  String dateString = DateFormatUtils.format(date, ISO8601_DATE_FORMAT, timeZone);
      
                  System.out.println(dateString);
              }
          }
      }

      when running the code above , there is over stack risk
      1. When invoking FastTimeZone.getTimeZone(timeZoneString), a new GmtTimeZone will be created

      GmtTimeZone(final boolean negate, final int hours, final int minutes) {
              if (hours >= HOURS_PER_DAY) {
                  throw new IllegalArgumentException(hours + " hours out of range");
              }
              if (minutes >= MINUTES_PER_HOUR) {
                  throw new IllegalArgumentException(minutes + " minutes out of range");
              }
              final int milliseconds = (minutes + (hours * MINUTES_PER_HOUR)) * MILLISECONDS_PER_MINUTE;
              offset = negate ? -milliseconds : milliseconds;
              zoneId = twoDigits(
                  twoDigits(new StringBuilder(9).append("GMT").append(negate ? '-' : '+'), hours)
                      .append(':'), minutes).toString();
      
          }
      

      the every GmtTimeZone instance , the zoneIds instance are different , even through the values are the same.

      2. When invoking DateFormatUtils.format(), there is a ConCurrentHashMap in FormatCache with key is MultipartKey. when invoking FormatCache.getInstance(), first get from cInstanceCache, if value is null, putIfAbsent, but because GmtTimeZone instances are different, when invoking GmtTimeZone.equals, the logic is

      @Override
          public boolean equals(final Object other) {
              if (!(other instanceof GmtTimeZone)) {
                  return false;
              }
              return zoneId == ((GmtTimeZone) other).zoneId;
          }
      

      every zoneId address are different so, equals function return false, but actually the zoneId values are the same.
      so FastDateFormat will be put into cInstanceCache in FormatCache again and again, which will increase the capability of the map, and cause over stack risk, also, it will cause application run much slower.

      Attachments

        Activity

          People

            Unassigned Unassigned
            wcs233 Xia Yun
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:

              Time Tracking

                Estimated:
                Original Estimate - Not Specified
                Not Specified
                Remaining:
                Remaining Estimate - 0h
                0h
                Logged:
                Time Spent - 1h 40m
                1h 40m