群里面有小伙伴提了个问题,说在看并发源码的时候,很多时候源码中都使用for(;;)而不是使用while(true),这两个有什么区别吗?
这种问题,在java里面,最简单有效的办法就是打印字节码看一下,javap再次华丽丽的登场:
实践
1. 首先编写一个java文件,内容如下:
public class Demo {
public void demo1() {
for (;;) {}
}
public void demo2() {
while (true) {}
}
}
2. 然后编译为class文件,并显示字节码:
zengyu@zengyu-Precision-T1700:~$ javac Demo.java
zengyu@zengyu-Precision-T1700:~$ javap -verbose Demo.class
Classfile /home/zengyu/Demo.class
Last modified 2018-9-12; size 314 bytes
MD5 checksum 5f959c0d031d1c2b2503d75222b0e94e
Compiled from "Demo.java"
public class Demo
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #3.#13 // java/lang/Object."<init>":()V
#2 = Class #14 // Demo
#3 = Class #15 // java/lang/Object
#4 = Utf8 <init>
#5 = Utf8 ()V
#6 = Utf8 Code
#7 = Utf8 LineNumberTable
#8 = Utf8 demo1
#9 = Utf8 StackMapTable
#10 = Utf8 demo2
#11 = Utf8 SourceFile
#12 = Utf8 Demo.java
#13 = NameAndType #4:#5 // "<init>":()V
#14 = Utf8 Demo
#15 = Utf8 java/lang/Object
{
public Demo();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0
public void demo1();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=0, locals=1, args_size=1
0: goto 0
LineNumberTable:
line 3: 0
StackMapTable: number_of_entries = 1
frame_type = 0 /* same */
public void demo2();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=0, locals=1, args_size=1
0: goto 0
LineNumberTable:
line 7: 0
StackMapTable: number_of_entries = 1
frame_type = 0 /* same */
}
SourceFile: "Demo.java"
3. 分析指令:
public void demo1();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=0, locals=1, args_size=1
0: goto 0
LineNumberTable:
line 3: 0
StackMapTable: number_of_entries = 1
frame_type = 0 /* same */
public void demo2();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=0, locals=1, args_size=1
0: goto 0
LineNumberTable:
line 7: 0
StackMapTable: number_of_entries = 1
frame_type = 0 /* same */
可以看出二者在编译为字节码后是完全一致的。
字节码一模一样,能有啥区别?因此,在java里面,就看个人的爱好了,二者没区别!
更过关于java字节码的内容可以观看我的一个视频课程:Java生产环境下性能监控与调优详解
为啥网上有的文章说二者有区别呢?因为那是在C语言中!
在C语言中, while(1)在编译后:
mov eax,1
test eax,eax
je foo+23h
jmp foo+18h
for(;;)在编译后:
mp foo+23
这里的区别就非常明显了,for(;;)在c语言中指令较少,也能够节省内存,没有判断跳转,是比while(1)更好的无限循环。