简体   繁体   English

为什么在Integer类的Integer.valueOf方法中使用assert?

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

I was digging into how the Integer class actually uses cached objects, and I found the below code in the Integer.valueOf method:我正在研究Integer类如何实际使用缓存对象,我在Integer.valueOf方法中找到了以下代码:

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:我的问题是:

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.在这里,这个断言记录了这样一个事实,当进入valueOf方法时, IntegerCache.high值保证至少为 127。最好写一个断言而不是注释,因为当相应的断言时,JVM 也会检查断言命令行选项 ( -esa ) 处于活动状态。

Normally this assert will never throw, because the IntegerCache.high is initialized in this way:通常这个断言永远不会抛出,因为IntegerCache.high是这样初始化的:

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.此代码保证该值至少为 127。因此,如果您修改IntegerCache.high (使用反射和setAccessible(true) )或者如果将来会修改 JDK 并且 IntegerCache 中将引入错误,则断言可能会抛出IntegerCache.high初始化代码。 That's why asserts exist: to catch bugs.这就是断言存在的原因:捕捉错误。

The JLS mandates that the integer cache must be in place for integers between -128 and 127. JLS 要求整数缓存必须用于 -128 到 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.)目前,Oracle 实现会强制执行此操作,但不会再执行此操作,因此缓存上限很可能会在将来的某个时候扩展(在实践中不太可能,但完全符合规范。)

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!但是,它永远不能小于127,否则实现将不再符合 JLS - 这将是一件大事,因此(我相信)为什么会有 assert 语句!

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.正如 biziclop 在评论中指出的那样,用户也可以通过传递 VM 参数来更改它 - 另一个(也许更引人注目)断言的原因。

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.另请注意,除非使用-ea运行,否则将跳过断言语句,因此在正常使用中,此检查绝对没有运行时开销。

The cache, normally for -128 ... 127, can be enlarged, which might be the reason: it should not become less.缓存,通常为 -128 ... 127,可以扩大,这可能是原因:它不应该变得更少。 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. As 断言对生产代码没有影响。

Looking at看着

http://www.docjar.com/html/api/java/lang/Integer.java.html 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.如果他们在parseInt使用了valueOf ,那么当parseInt在 VM 初始化的早期被调用时, high值实际上将为零。

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; 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.防止在 VM 初始化期间调用 valueOf 方法调用的代码。

  1. And when it will throw AssertionError in this scenario?在这种情况下它什么时候会抛出 AssertionError ?

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.如果您使用 -ea 选项(启用断言)运行 java 并且有一些调用 valueOf 的初始化代码,JVM 几乎会立即崩溃,因为 AssertionError。 Hopefully the Java team tests for this stuff and will fix the offending code before releasing that to the wild.希望 Java 团队测试这些东西,并在将其发布到野外之前修复有问题的代码。

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).与其他答案的断言相反,high 总是大于或等于 128,它似乎有时为零(不计算反射)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM