Why is assert used in the Integer.valueOf method of the Integer class?

China☆狼群 提交于 2020-01-01 07:28:09

问题


I was digging into how the Integer class actually uses cached objects, and I found the below code in the Integer.valueOf method:

public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

My question is:

  • what is the use of assert IntegerCache.high >= 127; I read that assert provides an effective way to detect and correct programming errors. But this is runtime code so why would someone use assert?
  • And when will it throw AssertionError in this scenario?

回答1:


The purpose of asserts is to establish invariants and to document the implementation. Here, this assert documents the fact that when the valueOf method is entered IntegerCache.high value is guaranteed to be at least 127. It's better to write an assert instead of the comment, because the assert will also be checked by the JVM when the corresponding command line option (-esa) is active.

Normally this assert will never throw, because the IntegerCache.high is initialized in this way:

int h = 127;
String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
    try {
        int i = parseInt(integerCacheHighPropValue);
        i = Math.max(i, 127);
        // Maximum array size is Integer.MAX_VALUE
        h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
    } catch( NumberFormatException nfe) {
        // If the property cannot be parsed into an int, ignore it.
    }
}
high = h;

This code guarantees that the value will be at least 127. So the assert can throw if you modify IntegerCache.high (using reflection and setAccessible(true)) or if the JDK will be modified in the future and bug will be introduced in IntegerCache.high initialization code. That's why asserts exist: to catch bugs.




回答2:


The JLS mandates that the integer cache must be in place for integers between -128 and 127.

At present, the Oracle implementation enforces this but no more, so the cache ceiling could well be extended at some point in the future (unlikely in practice, but it'd be completely in spec.)

However, it can never be less than 127, otherwise the implementation would no longer conform to the JLS - and that would be a pretty big deal, hence (I believe) why the assert statement is there!

As biziclop pointed out in the comments, it can also be changed by the user by passing a VM argument - another (and perhaps more compelling) reason the assertion is in place.

Also note that the assert statement will be skipped unless running with -ea, so in normal use there is absolutely no runtime overhead for this check.




回答3:


The cache, normally for -128 ... 127, can be enlarged, which might be the reason: it should not become less. And as the code would function even without cache, an assert might be a soft way: telling about a performance defect when developing. As asserts do no impact on production code.




回答4:


Looking at

http://www.docjar.com/html/api/java/lang/Integer.java.html

I see this comment

       /*
        * 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 they had used valueOf in parseInt then when parseInt is called early in VM initialization, the high value would actually be zero.

I am not sure what problems that would cause, but evidently someone thought it was worth guarding against.

  1. what is the use of assert IntegerCache.high >= 127; I read that assert provides an effective way to detect and correct programming errors. But this is runtime code why someone will use assert?

To guard against code invoked during VM initialization calling the valueOf method.

  1. And when it will throw AssertionError in this scenario?

If you run java with the -ea option (enabling assertions) and there is some initialization code that calls valueOf the JVM will almost immediately crash because of AssertionError. Hopefully the Java team tests for this stuff and will fix the offending code before releasing that to the wild.

Contrary to other answer's assertions that high will always be greater than or equal to 128, it appears that there are times it is zero (not counting reflection).



来源:https://stackoverflow.com/questions/33891156/why-is-assert-used-in-the-integer-valueof-method-of-the-integer-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!