Xia Yun created LANG-1641:
-----------------------------

             Summary: Over Stack Issue
                 Key: LANG-1641
                 URL: https://issues.apache.org/jira/browse/LANG-1641
             Project: Commons Lang
          Issue Type: Bug
          Components: lang.time.*
    Affects Versions: 3.7
            Reporter: Xia Yun


{code:java}
//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);
        }
    }
}{code}

when running the code above , there is over stack risk
1. When invoking FastTimeZone.getTimeZone(timeZoneString), a new GmtTimeZone 
will be created
{code:java}
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();

    }
{code}

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 
{code:java}
@Override
    public boolean equals(final Object other) {
        if (!(other instanceof GmtTimeZone)) {
            return false;
        }
        return zoneId == ((GmtTimeZone) other).zoneId;
    }
{code}
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.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to