更多:Java进阶核心知识集
包含:JVM,JAVA集合,网络,JAVA多线程并发,JAVA基础,Spring原理,微服务,Zookeeper,Kafka,RabbitMQ,Hbase,MongoDB,Cassandra,设计模式,负载均衡,数据库,一致性哈希,JAVA算法,数据结构,加密算法,分布式缓存等等
高效学习视频
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public void benchmark();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: bipush 32
2: invokestatic #2 // Method org/agoncal/sample/jmh/StringKit.getStringRandom:(I)Ljava/lang/String;
5: pop
6: return
LineNumberTable:
line 21: 0
line 22: 6
LocalVariableTable:
Start Length Slot Name Signature
0 7 0 this Lorg/agoncal/sample/jmh/Main;
RuntimeVisibleAnnotations:
0: #26()
public void benchmarkFinal();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: bipush 32
2: invokestatic #3 // Method org/agoncal/sample/jmh/StringKitFinal.getStringRandomFinal:(I)Ljava/lang/String;
5: pop
6: return
LineNumberTable:
line 26: 0
line 27: 6
LocalVariableTable:
Start Length Slot Name Signature
0 7 0 this Lorg/agoncal/sample/jmh/Main;
RuntimeVisibleAnnotations:
0: #26()
可以看到,它们在调用者上面的字节码也没有什么区别,只是方法名不一样之外。
对于 JVM 来说,它是只认字节码的,既然字节码除了方法名和修饰符一样,其他都一样,那就可以大概推测它们的性能几乎可以忽略不计了。因为调用 static final 和 static 非 final 的JVM指令是一样。
无 static 修饰
方法体是一样的,只是将它们删除了 static 的修饰。
结果
1 |
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# JMH version: 1.19
VM version: JDK 1.8.0_92, VM 25.92-b14
VM invoker: /srv/jdk1.8.0_92/jre/bin/java
VM options: <none>
Warmup: 20 iterations, 1 s each
Measurement: 20 iterations, 1 s each
Timeout: 10 min per iteration
Threads: 1 thread, will synchronize iterations
Benchmark mode: Throughput, ops/time
Benchmark: org.agoncal.sample.jmh.Main.benchmark
中间忽略了预热及测试过程,这里只显示结果
Result “org.agoncal.sample.jmh.Main.benchmark”:
201306.770 ±(99.9%) 8184.423 ops/s [Average]
(min, avg, max) = (131889.934, 201306.770, 259928.172), stdev = 34653.361
CI (99.9%): [193122.347, 209491.193] (assumes normal distribution)
JMH version: 1.19
VM version: JDK 1.8.0_92, VM 25.92-b14
VM invoker: /srv/jdk1.8.0_92/jre/bin/java
VM options: <none>
Warmup: 20 iterations, 1 s each
Measurement: 20 iterations, 1 s each
Timeout: 10 min per iteration
Threads: 1 thread, will synchronize iterations
Benchmark mode: Throughput, ops/time
Benchmark: org.agoncal.sample.jmh.Main.benchmarkFinal
中间忽略了预热及测试过程,这里只显示结果
Result “org.agoncal.sample.jmh.Main.benchmarkFinal”:
196871.022 ±(99.9%) 8595.719 ops/s [Average]
(min, avg, max) = (131182.268, 196871.022, 265522.769), stdev = 36394.814
CI (99.9%): [188275.302, 205466.741] (assumes normal distribution)
Run complete. Total time: 00:13:35
Benchmark Mode Cnt Score Error Units
Main.benchmark thrpt 200 201306.770 ± 8184.423 ops/s
Main.benchmarkFinal thrpt 200 196871.022 ± 8595.719 ops/s
分析
字节码级别的差别
1 |
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
[19:20:17] emacsist:target $ diff /tmp/stringkit.log /tmp/stringkit-final.log
1,5c1,5
< Classfile /Users/emacsist/Documents/idea/logging/target/classes/org/agoncal/sample/jmh/StringKit.class
< Last modified 2017-6-15; size 1110 bytes
< MD5 checksum f61144e86f7c17dc5d5f2b2d35fac36d
< Compiled from “StringKit.java”
< public class org.agoncal.sample.jmh.StringKit
> Classfile /Users/emacsist/Documents/idea/logging/target/classes/org/agoncal/sample/jmh/StringKitFinal.class
> Last modified 2017-6-15; size 1130 bytes
> MD5 checksum 15ce17ee17fdb5f4721f0921977b1e69
> Compiled from “StringKitFinal.java”
> public class org.agoncal.sample.jmh.StringKitFinal
24c24
< #15 = Class #52 // org/agoncal/sample/jmh/StringKit
> #15 = Class #52 // org/agoncal/sample/jmh/StringKitFinal
32,33c32,33
< #23 = Utf8 Lorg/agoncal/sample/jmh/StringKit;
< #24 = Utf8 getStringRandom
> #23 = Utf8 Lorg/agoncal/sample/jmh/StringKitFinal;
> #24 = Utf8 getStringRandomFinal
47c47
< #38 = Utf8 StringKit.java
> #38 = Utf8 StringKitFinal.java
61c61
< #52 = Utf8 org/agoncal/sample/jmh/StringKit
> #52 = Utf8 org/agoncal/sample/jmh/StringKitFinal
75c75
< public org.agoncal.sample.jmh.StringKit();
> public org.agoncal.sample.jmh.StringKitFinal();
87c87
< 0 5 0 this Lorg/agoncal/sample/jmh/StringKit;
> 0 5 0 this Lorg/agoncal/sample/jmh/StringKitFinal;
89c89
< public java.lang.String getStringRandom(int);
> public final java.lang.String getStringRandomFinal(int);
91c91
< flags: ACC_PUBLIC
> flags: ACC_PUBLIC, ACC_FINAL
169c169
< 0 125 0 this Lorg/agoncal/sample/jmh/StringKit;
> 0 125 0 this Lorg/agoncal/sample/jmh/StringKitFinal;
188c188
< SourceFile: “StringKit.java”
> SourceFile: “StringKitFinal.java”
可以看到,字节码上除了名字和 final 修饰符差别外,其余的是一样的。
在调用者上面的字节码差别
1 |
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public void benchmark();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: new #2 // class org/agoncal/sample/jmh/StringKit
3: dup
4: invokespecial #3 // Method org/agoncal/sample/jmh/StringKit.“<init>”😦)V
7: bipush 32
9: invokevirtual #4 // Method org/agoncal/sample/jmh/StringKit.getStringRandom:(I)Ljava/lang/String;
12: pop
13: return
LineNumberTable:
line 21: 0
line 22: 13
LocalVariableTable:
Start Length Slot Name Signature
0 14 0 this Lorg/agoncal/sample/jmh/Main;
RuntimeVisibleAnnotations:
0: #30()
public void benchmarkFinal();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: new #5 // class org/agoncal/sample/jmh/StringKitFinal
3: dup
4: invokespecial #6 // Method org/agoncal/sample/jmh/StringKitFinal.“<init>”😦)V
7: bipush 32
9: invokevirtual #7 // Method org/agoncal/sample/jmh/StringKitFinal.getStringRandomFinal:(I)Ljava/lang/String;
12: pop
13: return
LineNumberTable:
line 26: 0
line 27: 13
LocalVariableTable:
Start Length Slot Name Signature
0 14 0 this Lorg/agoncal/sample/jmh/Main;
RuntimeVisibleAnnotations:
0: #30()
可以看到,它们除了名字不同之外,其他的JVM指令都是一样的。
总结
对于是否有 final 修饰的方法,对性能的影响可以忽略不计。因为它们生成的字节码除了 flags 标志位是否有 final 修饰不同之外,其他所有的JVM指令,都是一样的(对于方法本身,以及调用者本身的字节码都一样)。对于JVM来说,它执行的就是字节码,如果字节码都一样的话,那对于JVM来说,它就是同一样东西的了。
有继承
===
无 final 修饰
1 |
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package org.agoncal.sample.jmh;
import java.util.Random;
/**
- Created by emacsist on 2017/6/15.
*/
public abstract class StringKitAbs {
// 生成随机数字和字母,
public String getStringRandom(int length) {
String val = “”;
Random random = new Random();
// 参数length,表示生成几位随机数
for (int i = 0; i < length; i++) {
String charOrNum = random.nextInt(2) % 2 == 0 ? “char” : “num”;
// 输出字母还是数字
if (“char”.equalsIgnoreCase(charOrNum)) {
// 输出是大写字母还是小写字母
// int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;
val += (char) (random.nextInt(26) + 97);
} else if (“num”.equalsIgnoreCase(charOrNum)) {
val += String.valueOf(random.nextInt(10));
}
}
return val;
}
}
有 final 修饰
1 |
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package org.agoncal.sample.jmh;
import java.util.Random;
/**
- Created by emacsist on 2017/6/15.
*/
public abstract class StringKitAbsFinal {
// 生成随机数字和字母,
public final String getStringRandomFinal(int length) {
String val = “”;
Random random = new Random();
// 参数length,表示生成几位随机数
for (int i = 0; i < length; i++) {
String charOrNum = random.nextInt(2) % 2 == 0 ? “char” : “num”;
// 输出字母还是数字
if (“char”.equalsIgnoreCase(charOrNum)) {
// 输出是大写字母还是小写字母
// int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;
val += (char) (random.nextInt(26) + 97);
} else if (“num”.equalsIgnoreCase(charOrNum)) {
val += String.valueOf(random.nextInt(10));
}
}
return val;
}
}
测试代码
写一个类来继承上面的抽象类,以此来测试在继承中 final 有否对多态中的影响
1 |
2
3
4
5
6
package org.agoncal.sample.jmh;
/**
- Created by emacsist on 2017/6/15.
*/
public class StringKitFinal extends StringKitAbsFinal {
}
1 |
2
3
4
5
6
package org.agoncal.sample.jmh;
/**
- Created by emacsist on 2017/6/15.
*/
public class StringKit extends StringKitAbs {
}
然后在基准测试中:
1 |
2
3
4
5
6
7
8
@Benchmark
public void benchmark() {
new StringKit().getStringRandom(32);
}
@Benchmark
public void benchmarkFinal() {
new StringKitFinal().getStringRandomFinal(32);
}
测试结果
非 final 结果
1 |
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# JMH version: 1.19
VM version: JDK 1.8.0_92, VM 25.92-b14
VM invoker: /srv/jdk1.8.0_92/jre/bin/java
VM options: <none>
Warmup: 20 iterations, 1 s each
Measurement: 20 iterations, 1 s each
Timeout: 10 min per iteration
Threads: 1 thread, will synchronize iterations
Benchmark mode: Throughput, ops/time
Benchmark: org.agoncal.sample.jmh.Main.benchmark
中间忽略了预热及测试过程
Result “org.agoncal.sample.jmh.Main.benchmark”:
213462.677 ±(99.9%) 8670.164 ops/s [Average]
(min, avg, max) = (135751.428, 213462.677, 264182.887), stdev = 36710.017
CI (99.9%): [204792.513, 222132.841] (assumes normal distribution)
有 final 结果
1 |
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# JMH version: 1.19
VM version: JDK 1.8.0_92, VM 25.92-b14
VM invoker: /srv/jdk1.8.0_92/jre/bin/java
VM options: <none>
Warmup: 20 iterations, 1 s each
Measurement: 20 iterations, 1 s each
Timeout: 10 min per iteration
Threads: 1 thread, will synchronize iterations
Benchmark mode: Throughput, ops/time
Benchmark: org.agoncal.sample.jmh.Main.benchmarkFinal
中间忽略了预热及测试过程
Result “org.agoncal.sample.jmh.Main.benchmarkFinal”:
213684.585 ±(99.9%) 8571.512 ops/s [Average]
(min, avg, max) = (133472.162, 213684.585, 267742.236), stdev = 36292.318
CI (99.9%): [205113.073, 222256.097] (assumes normal distribution)
总对比
1 |
2
3
4
# Run complete. Total time: 00:13:35
Benchmark Mode Cnt Score Error Units
Main.benchmark thrpt 200 213462.677 ± 8670.164 ops/s
Main.benchmarkFinal thrpt 200 213684.585 ± 8571.512 ops/s
它们字节码的区别
1 |
总结
总的来说,面试是有套路的,一面基础,二面架构,三面个人。
最后,小编这里收集整理了一些资料,其中包括面试题(含答案)、书籍、视频等。希望也能帮助想进大厂的朋友
oughput, ops/time
Benchmark: org.agoncal.sample.jmh.Main.benchmarkFinal
中间忽略了预热及测试过程
Result “org.agoncal.sample.jmh.Main.benchmarkFinal”:
213684.585 ±(99.9%) 8571.512 ops/s [Average]
(min, avg, max) = (133472.162, 213684.585, 267742.236), stdev = 36292.318
CI (99.9%): [205113.073, 222256.097] (assumes normal distribution)
总对比
1 |
2
3
4
# Run complete. Total time: 00:13:35
Benchmark Mode Cnt Score Error Units
Main.benchmark thrpt 200 213462.677 ± 8670.164 ops/s
Main.benchmarkFinal thrpt 200 213684.585 ± 8571.512 ops/s
它们字节码的区别
1 |
总结
总的来说,面试是有套路的,一面基础,二面架构,三面个人。
最后,小编这里收集整理了一些资料,其中包括面试题(含答案)、书籍、视频等。希望也能帮助想进大厂的朋友
[外链图片转存中…(img-ILWBTiBA-1715443935611)]
[外链图片转存中…(img-PmdRwZMs-1715443935612)]