Java中编译器的代码优化 - 执行"if"条件所用的时间为零

The*_*ind 5 java

我有以下代码..

 public static void main(String[] args) {
            int i = 1234;
            int j = 1234;
            int k = 4321;
            long l1 = System.nanoTime();
            if (i == j) {
                System.out.println("equal");
            }
            System.out.println(System.nanoTime() - l1);
            l1 = System.nanoTime();

            if (i != k) {
                System.out.println("equal");
            }

            System.out.println(System.nanoTime() - l1);
            l1 = System.nanoTime();

            if (i == k) {
                System.out.println("equal");
            }

            System.out.println(System.nanoTime() - l1);


            l1 = System.nanoTime();

            if (i != j) {
                System.out.println("equal");
            }
            System.out.println(System.nanoTime() - l1);

        }
Run Code Online (Sandbox Code Playgroud)

现在当我运行这个程序时,OP是:

1. 
equal
190295
equal
22237
427
0

2. 
equal
156512
equal
18388
0
428

3. 
equal
155656
equal
20099
0
0
Run Code Online (Sandbox Code Playgroud)

我的问题:如何执行所花费的时间是"0"??如果编译器做了一些优化,那为什么不总是这样做呢?我认为"0"是因为该语句没有被编译器执行.

ass*_*ias 4

实际原因

输出各不相同,有时为 0,有时则不像您已经注意到的那样。最可能的问题是System.nanoTime

提供纳秒精度,但不一定是纳秒分辨率(即值变化的频率)

所以 0 并不一定意味着 0 - 它只是意味着:小于时钟可以表示的最小“滴答声”。


我们能否确定代码没有被编译器优化过?

如果您-XX:+PrintCompilation在运行程序时使用该标志,您将得到类似于下面的输出。如果你仔细阅读,你会注意到 main 还没有被 JIT 编译(这是有道理的,因为它并不是很热)——所以你的代码不可能被优化掉。

 62    1       3       java.lang.String::hashCode (55 bytes)
 62    3       3       java.lang.String::indexOf (70 bytes)
 63    2       3       java.lang.String::charAt (29 bytes)
 65    4       3       java.lang.AbstractStringBuilder::ensureCapacityInternal (16 bytes)
 65    5       3       java.lang.Object::<init> (1 bytes)
 65    8     n 0       java.lang.System::arraycopy (native)   (static)
 65    6       3       java.lang.CharacterData::of (120 bytes)
 66    7       3       java.lang.CharacterDataLatin1::getProperties (11 bytes)
 66    9       3       java.lang.Character::toLowerCase (9 bytes)
 66   10       3       java.lang.CharacterDataLatin1::toLowerCase (39 bytes)
 66   11       3       java.lang.String::length (6 bytes)
 66   12       3       java.lang.AbstractStringBuilder::append (29 bytes)
 66   13       3       java.lang.StringBuilder::append (8 bytes)
 67   14       3       java.io.WinNTFileSystem::isSlash (18 bytes)
 67   15  s    3       java.lang.StringBuffer::append (13 bytes)
 67   16       3       java.lang.String::<init> (62 bytes)
 68   17       3       java.lang.String::equals (81 bytes)
 68   18       1       java.lang.Object::<init> (1 bytes)
 68    5       3       java.lang.Object::<init> (1 bytes)   made not entrant
 68   19       3       java.lang.String::getChars (62 bytes)
 74   20       3       java.lang.Math::min (11 bytes)
 74   21       3       java.io.BufferedInputStream::getBufIfOpen (21 bytes)
 74   22       3       java.util.Arrays::copyOfRange (63 bytes)
 75   24       3       java.io.DataInputStream::readUTF (501 bytes)
 76   29       3       java.io.DataInputStream::readFully (63 bytes)
 77   26  s    3       java.io.BufferedInputStream::read (113 bytes)
 77   23  s    3       java.io.BufferedInputStream::read (49 bytes)
 77   30       3       java.io.DataInputStream::readShort (40 bytes)
 78   25       3       java.io.DataInputStream::readUTF (5 bytes)
 78   27       3       java.io.BufferedInputStream::read1 (108 bytes)
 78   28       3       java.io.DataInputStream::readUnsignedShort (39 bytes)
 78   31       3       java.util.HashMap::hash (20 bytes)
 79   32  s    3       java.io.ByteArrayInputStream::read (36 bytes)
 79   33       3       java.io.DataInputStream::readByte (23 bytes)
 79   34       3       sun.util.calendar.ZoneInfoFile::indexOf (32 bytes)
 80   35       3       java.util.zip.CRC32::update (16 bytes)
 81   36     n 0       java.util.zip.CRC32::updateBytes (native)   (static)
 81   37       3       sun.util.calendar.ZoneInfoFile$Checksum::update (39 bytes)
 83   39       3       java.util.HashMap::putVal (300 bytes)
 84   41       4       java.lang.String::equals (81 bytes)
 84   38       3       java.util.HashMap::put (13 bytes)
 84   42   !   3       java.io.BufferedReader::readLine (304 bytes)
 86   43       3       java.util.LinkedList::indexOf (73 bytes)
 86   44       3       java.util.HashMap::getNode (148 bytes)
 86   46       3       java.util.HashMap::get (23 bytes)
 87   47       3       sun.misc.JarIndex::addToList (59 bytes)
 87   17       3       java.lang.String::equals (81 bytes)   made not entrant
 87   45       3       java.util.HashMap$Node::<init> (26 bytes)
 87   40       3       java.util.HashMap::newNode (13 bytes)
 88   48       4       java.lang.String::charAt (29 bytes)
 88    2       3       java.lang.String::charAt (29 bytes)   made not entrant
 92   49       3       java.lang.AbstractStringBuilder::append (50 bytes)
 92   50       3       java.lang.System::getSecurityManager (4 bytes)
 93   51       3       java.lang.Math::max (11 bytes)
 93   52       3       java.lang.String::endsWith (17 bytes)
 96   53       3       java.lang.StringBuilder::append (8 bytes)
equal
189546
equal
17232
367
0

 97   54       1       java.nio.Buffer::position (5 bytes)
Run Code Online (Sandbox Code Playgroud)