Java编译带来的错误判断

最近朋友圈里有人发了张图如下:
在这里插入图片描述
问朋友圈的大神有没有人能解释:为什么带“break”的双重for循环比不带“break”的循环花费的时间多。循环的次数少的却用了更长的时间?
于是我就现出几个疑问:

  1. 真的是这样吗?
  2. 如果真的是这样,Java脑子是不是有坑儿
  3. 自己动手开始写
    代码如下:
public class CompileTest {

	public static void main(String[] args) {
		test1();
		test2();
	}

	public static void test1() {
		long time1 = System.currentTimeMillis();
		long count1 = 0;
		for (int i = 0; i < 50000; i++) {
			for (int j = 0; j < 50000; j++) {
				if (j > 30000) {

				}
				count1++;
			}
		}
		System.err.println(System.currentTimeMillis() - time1 + "-----" + count1);
	}

	public static void test2() {
		long time2 = System.currentTimeMillis();
		long count2 = 0;
		for (int i = 0; i < 50000; i++) {
			for (int j = 0; j < 50000; j++) {
				if (j > 30000) {
					break;
				}
				count2++;
			}
		}
		System.err.println(System.currentTimeMillis() - time2 + "-----" + count2);
		System.err.println("==========================================");
	}
}

这里为了一会儿方便看日志,用了错误打印(字体为红色)
运行之后结果如下:
在这里插入图片描述
结果真的是这样,带break的循环次数少,但是花费的时间却更多,这是为什么?
连续运行了好几次,都是同样的结果,这不科学啊!
如果我用for循环多运行几次呢?更改了main方法:

	public static void main(String[] args) {
		for (int i = 0; i < 100; i++) {
			test1();
			test2();
		}
	}

运行结果如下:
在这里插入图片描述
结果显示第一次循环跟之前的结果一样,第二次开始结果就不一样,循环少的运行时间就少。于是我猜测这是Java的编译机制导致的。
开始验证我的猜测:
启动参数上添加编译日志打印:-XX:+PrintCompilation
运行结果如下:

     97    1       3       java.lang.Object::<init> (1 bytes)
     99    2       3       java.lang.String::equals (81 bytes)
    100    3       3       java.lang.String::hashCode (55 bytes)
    100    4       3       java.lang.AbstractStringBuilder::ensureCapacityInternal (27 bytes)
    100    5       4       java.lang.String::charAt (29 bytes)
    101    6       3       java.lang.String::getChars (62 bytes)
    104    7       3       java.lang.Character::toLowerCase (9 bytes)
    104   12     n 0       java.lang.System::arraycopy (native)   (static)
    104   13       3       java.lang.String::indexOf (70 bytes)
    104   14       4       java.lang.String::length (6 bytes)
    105    8       3       java.lang.CharacterData::of (120 bytes)
    105    9       3       java.lang.CharacterDataLatin1::toLowerCase (39 bytes)
    105   10       3       java.lang.CharacterDataLatin1::getProperties (11 bytes)
    105   17       3       java.io.WinNTFileSystem::isSlash (18 bytes)
    106   16       3       java.lang.AbstractStringBuilder::append (29 bytes)
    106   18  s    3       java.lang.StringBuffer::append (13 bytes)
    107   11       3       java.lang.Math::min (11 bytes)
    108   15       3       java.util.Arrays::copyOfRange (63 bytes)
    109   19       3       java.lang.Character::toLowerCase (6 bytes)
    110   20       3       java.lang.String::indexOf (7 bytes)
    110   21       1       java.io.File::getPath (5 bytes)
    110   22       3       sun.nio.cs.ext.DoubleByte$Encoder::encodeChar (21 bytes)
    110   23       3       java.lang.String::toLowerCase (439 bytes)
    112   24       3       java.lang.AbstractStringBuilder::append (50 bytes)
    112   26       3       java.lang.StringBuilder::append (8 bytes)
    112   25       1       java.net.URL::getProtocol (5 bytes)
    115   27       3       java.util.HashMap::hash (20 bytes)
    116   28 %     3       com.xyl.test.CompileTest::test1 @ 18 (76 bytes)
    117   29 %     4       com.xyl.test.CompileTest::test1 @ 18 (76 bytes)
    119   28 %     3       com.xyl.test.CompileTest::test1 @ -2 (76 bytes)   made not entrant
    187   29 %     4       com.xyl.test.CompileTest::test1 @ -2 (76 bytes)   made not entrant
73-----2500000000
    188   30 %     3       com.xyl.test.CompileTest::test2 @ 18 (95 bytes)
    189   31 %     4       com.xyl.test.CompileTest::test2 @ 18 (95 bytes)
    192   30 %     3       com.xyl.test.CompileTest::test2 @ -2 (95 bytes)   made not entrant
637-----1500050000
==========================================
    825   32 %     3       com.xyl.test.CompileTest::test1 @ 18 (76 bytes)
    826   33 %     4       com.xyl.test.CompileTest::test1 @ 18 (76 bytes)
    829   32 %     3       com.xyl.test.CompileTest::test1 @ -2 (76 bytes)   made not entrant
53-----2500000000
    878   34       4       com.xyl.test.CompileTest::test2 (95 bytes)
744-----1500050000
==========================================
   1622   35       4       com.xyl.test.CompileTest::test1 (76 bytes)
48-----2500000000
   1699   34       4       com.xyl.test.CompileTest::test2 (95 bytes)   made not entrant
28-----1500050000
==========================================
   1748   35       4       com.xyl.test.CompileTest::test1 (76 bytes)   made not entrant
49-----2500000000
   1748   36       3       com.xyl.test.CompileTest::test2 (95 bytes)
734-----1500050000
==========================================
   2481   37       3       com.xyl.test.CompileTest::test1 (76 bytes)
47-----2500000000
   2528   38       1       java.nio.Buffer::position (5 bytes)
636-----1500050000
==========================================
61-----2500000000
682-----1500050000
==========================================
48-----2500000000
   3956   39       1       java.nio.Buffer::limit (5 bytes)
711-----1500050000
==========================================
65-----2500000000
704-----1500050000
==========================================
49-----2500000000
699-----1500050000
==========================================
48-----2500000000
   6232   40       4       com.xyl.test.CompileTest::test2 (95 bytes)
   6236   36       3       com.xyl.test.CompileTest::test2 (95 bytes)   made not entrant
870-----1500050000
==========================================
   7102   41       3       java.nio.ByteBuffer::arrayOffset (35 bytes)
   7103   42       4       com.xyl.test.CompileTest::test1 (76 bytes)
   7108   37       3       com.xyl.test.CompileTest::test1 (76 bytes)   made not entrant
67-----2500000000
29-----1500050000
==========================================
48-----2500000000
29-----1500050000
==========================================
50-----2500000000
   7325   43       3       java.nio.Buffer::position (43 bytes)
28-----1500050000
==========================================
   7354   44       1       java.lang.Object::<init> (1 bytes)
   7354    1       3       java.lang.Object::<init> (1 bytes)   made not entrant
58-----2500000000
29-----1500050000
==========================================
   7441   45       3       java.nio.CharBuffer::arrayOffset (35 bytes)
48-----2500000000
29-----1500050000
==========================================
48-----2500000000
30-----1500050000
==========================================
50-----2500000000
28-----1500050000
==========================================
47-----2500000000
29-----1500050000
==========================================
49-----2500000000
30-----1500050000
==========================================
49-----2500000000
35-----1500050000
==========================================
48-----2500000000
28-----1500050000
==========================================
   7991   46       3       java.nio.charset.CoderResult::isUnderflow (13 bytes)
   7992   47       3       java.nio.ByteBuffer::array (35 bytes)
68-----2500000000
   8060   48       3       java.io.BufferedWriter::ensureOpen (18 bytes)
   8060   49       1       sun.nio.cs.StreamEncoder::isOpen (5 bytes)
50-----1500050000
==========================================

在这里插入图片描述
当编译到上图所示的地方时,test2方法已经编译(优化)完了(因为后面的日志不再有test2方法的编译信息),也是从这里开始,后面带break循环次数少的所消耗的时间更少。
至此得出结论,如果只运行一次,Java是解释运行,所以看到的结果跟我们预期的不一样,而多次调用的时候,Java会进行编译优化(每运行一次都会收集信息,便于优化编译)。

猜你喜欢

转载自blog.csdn.net/qq_20280007/article/details/85047538
今日推荐