# HG changeset patch # User alanb # Date 1237903544 0 # Node ID 99a19a90813e09edd89101fa154cb753702ad970 # Parent 3663fccf2fc3948900842a08a3dc9cad3d2d09aa 6807702: Integer.valueOf cache should be configurable Reviewed-by: darcy diff -r 3663fccf2fc3 -r 99a19a90813e jdk/src/share/classes/java/lang/Integer.java --- a/jdk/src/share/classes/java/lang/Integer.java Tue Mar 24 14:03:46 2009 +0000 +++ b/jdk/src/share/classes/java/lang/Integer.java Tue Mar 24 14:05:44 2009 +0000 @@ -25,6 +25,8 @@ package java.lang; +import java.util.Properties; + /** * The {@code Integer} class wraps a value of the primitive type * {@code int} in an object. An object of type {@code Integer} @@ -442,6 +444,12 @@ public static int parseInt(String s, int radix) throws NumberFormatException { + /* + * WARNING: This method may be invoked early during VM initialization + * before IntegerCache is initialized. Care must be taken to not use + * the valueOf method. + */ + if (s == null) { throw new NumberFormatException("null"); } @@ -545,7 +553,7 @@ * does not contain a parsable {@code int}. */ public static Integer valueOf(String s, int radix) throws NumberFormatException { - return new Integer(parseInt(s,radix)); + return Integer.valueOf(parseInt(s,radix)); } /** @@ -570,20 +578,56 @@ * @exception NumberFormatException if the string cannot be parsed * as an integer. */ - public static Integer valueOf(String s) throws NumberFormatException - { - return new Integer(parseInt(s, 10)); + public static Integer valueOf(String s) throws NumberFormatException { + return Integer.valueOf(parseInt(s, 10)); + } + + /** + * Cache to support the object identity semantics of autoboxing for values between + * -128 and 127 (inclusive) as required by JLS. + * + * The cache is initialized on first usage. During VM initialization the + * getAndRemoveCacheProperties method may be used to get and remove any system + * properites that configure the cache size. At this time, the size of the + * cache may be controlled by the -XX:AutoBoxCacheMax= option. + */ + + // value of java.lang.Integer.IntegerCache.high property (obtained during VM init) + private static String integerCacheHighPropValue; + + static void getAndRemoveCacheProperties() { + if (!sun.misc.VM.isBooted()) { + Properties props = System.getProperties(); + integerCacheHighPropValue = + (String)props.remove("java.lang.Integer.IntegerCache.high"); + if (integerCacheHighPropValue != null) + System.setProperties(props); // remove from system props + } } private static class IntegerCache { - private IntegerCache(){} - - static final Integer cache[] = new Integer[-(-128) + 127 + 1]; + static final int low = -128; + static final int high; + static final Integer cache[]; static { - for(int i = 0; i < cache.length; i++) - cache[i] = new Integer(i - 128); + // high value may be configured by property + int h = 127; + if (integerCacheHighPropValue != null) { + int i = parseInt(integerCacheHighPropValue); + i = Math.max(i, 127); + // Maximum array size is Integer.MAX_VALUE + h = Math.min(i, Integer.MAX_VALUE - (-low)); + } + high = h; + + cache = new Integer[(high - low) + 1]; + int j = low; + for(int k = 0; k < cache.length; k++) + cache[k] = new Integer(j++); } + + private IntegerCache() {} } /** @@ -599,10 +643,9 @@ * @since 1.5 */ public static Integer valueOf(int i) { - final int offset = 128; - if (i >= -128 && i <= 127) { // must cache - return IntegerCache.cache[i + offset]; - } + assert IntegerCache.high >= 127; + if (i >= IntegerCache.low && i <= IntegerCache.high) + return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); } @@ -806,7 +849,7 @@ */ public static Integer getInteger(String nm, int val) { Integer result = getInteger(nm, null); - return (result == null) ? new Integer(val) : result; + return (result == null) ? Integer.valueOf(val) : result; } /** @@ -938,7 +981,7 @@ try { result = Integer.valueOf(nm.substring(index), radix); - result = negative ? new Integer(-result.intValue()) : result; + result = negative ? Integer.valueOf(-result.intValue()) : result; } catch (NumberFormatException e) { // If number is Integer.MIN_VALUE, we'll end up here. The next line // handles this case, and causes any genuine format error to be diff -r 3663fccf2fc3 -r 99a19a90813e jdk/src/share/classes/java/lang/Long.java --- a/jdk/src/share/classes/java/lang/Long.java Tue Mar 24 14:03:46 2009 +0000 +++ b/jdk/src/share/classes/java/lang/Long.java Tue Mar 24 14:05:44 2009 +0000 @@ -510,7 +510,7 @@ * contain a parsable {@code long}. */ public static Long valueOf(String s, int radix) throws NumberFormatException { - return new Long(parseLong(s, radix)); + return Long.valueOf(parseLong(s, radix)); } /** @@ -537,7 +537,7 @@ */ public static Long valueOf(String s) throws NumberFormatException { - return new Long(parseLong(s, 10)); + return Long.valueOf(parseLong(s, 10)); } private static class LongCache { @@ -650,7 +650,7 @@ try { result = Long.valueOf(nm.substring(index), radix); - result = negative ? new Long(-result.longValue()) : result; + result = negative ? Long.valueOf(-result.longValue()) : result; } catch (NumberFormatException e) { // If number is Long.MIN_VALUE, we'll end up here. The next line // handles this case, and causes any genuine format error to be @@ -869,7 +869,7 @@ */ public static Long getLong(String nm, long val) { Long result = Long.getLong(nm, null); - return (result == null) ? new Long(val) : result; + return (result == null) ? Long.valueOf(val) : result; } /** diff -r 3663fccf2fc3 -r 99a19a90813e jdk/src/share/classes/java/lang/System.java --- a/jdk/src/share/classes/java/lang/System.java Tue Mar 24 14:03:46 2009 +0000 +++ b/jdk/src/share/classes/java/lang/System.java Tue Mar 24 14:05:44 2009 +0000 @@ -1105,6 +1105,13 @@ props = new Properties(); initProperties(props); sun.misc.Version.init(); + + // Gets and removes system properties that configure the Integer + // cache used to support the object identity semantics of autoboxing. + // At this time, the size of the cache may be controlled by the + // -XX:AutoBoxCacheMax= option. + Integer.getAndRemoveCacheProperties(); + FileInputStream fdIn = new FileInputStream(FileDescriptor.in); FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out); FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err); diff -r 3663fccf2fc3 -r 99a19a90813e jdk/test/java/lang/Integer/ValueOf.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/Integer/ValueOf.java Tue Mar 24 14:05:44 2009 +0000 @@ -0,0 +1,55 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6807702 + * @summary Basic test for Integer.valueOf + * @run main ValueOf + * @run main/othervm -esa -XX:+AggressiveOpts ValueOf + */ + +public class ValueOf { + + // test Integer.valueOf over this range (inclusive) + private static final int TEST_LOW = -1024; + private static final int TEST_HIGH = 24576; + + public static void main(String[] args) { + int i = TEST_LOW; + while (i <= TEST_HIGH) { + // check that valueOf stores i + if (Integer.valueOf(i).intValue() != i) + throw new RuntimeException(); + + // check that the same object is returned for integral values + // in the range -128 to 127 (inclusive) + if (i >= -128 && i <= 127) { + if (Integer.valueOf(i) != Integer.valueOf(i)) + throw new RuntimeException(); + } + + i++; + } + } +}