理解字节码
Classfile /D:/java/Demo/JVM/ZiJieMa/target/classes/text.class
Last modified 2021年3月5日; size 546 bytes
MD5 checksum 99d62166e73d1405deac177780929589
Compiled from “text.java”
public class text
minor version: 0
major version: 49
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #4 // text
super_class: #5 // java/lang/Object
interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
#1 = Methodref #5.#23 // java/lang/Object.""😦)V
#2 = Fieldref #24.#25 // java/lang/System.out:Ljava/io/PrintStream;
#3 = Methodref #26.#27 // java/io/PrintStream.println:(I)V
#4 = Class #28 // text
#5 = Class #29 // java/lang/Object
#6 = Utf8
#7 = Utf8 ()V
#8 = Utf8 Code
#9 = Utf8 LineNumberTable
#10 = Utf8 LocalVariableTable
#11 = Utf8 this
#12 = Utf8 Ltext;
#13 = Utf8 main
#14 = Utf8 ([Ljava/lang/String;)V
#15 = Utf8 args
#16 = Utf8 [Ljava/lang/String;
#17 = Utf8 a
#18 = Utf8 I
#19 = Utf8 b
#20 = Utf8 c
#21 = Utf8 SourceFile
#22 = Utf8 text.java
#23 = NameAndType #6:#7 // “”😦)V
#24 = Class #30 // java/lang/System
#25 = NameAndType #31:#32 // out:Ljava/io/PrintStream;
#26 = Class #33 // java/io/PrintStream
#27 = NameAndType #34:#35 // println:(I)V
#28 = Utf8 text
#29 = Utf8 java/lang/Object
#30 = Utf8 java/lang/System
#31 = Utf8 out
#32 = Utf8 Ljava/io/PrintStream;
#33 = Utf8 java/io/PrintStream
#34 = Utf8 println
#35 = Utf8 (I)V
{
public text();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object.""😦)V
4: return
LineNumberTable:
line 1: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Ltext;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=1
0: iconst_2
1: istore_1
2: iconst_5
3: istore_2
4: iload_2
5: iload_1
6: isub
7: istore_3
8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
11: iload_3
12: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
15: return
LineNumberTable:
line 3: 0
line 4: 2
line 5: 4
line 6: 8
line 7: 15
LocalVariableTable:
Start Length Slot Name Signature
0 16 0 args [Ljava/lang/String;
2 14 1 a I
4 12 2 b I
8 8 3 c I
}
SourceFile: “text.java”
**
第一部分:显示了生成这个class的java源文件、版本信息、生成时间等。
第二部分:显示了该类中所涉及到常量池,共35个常量。
第三部分:显示该类的构造器,编译器自动插入的。
第四部分:显示了main方的信息。**
官方常量文档:
字段描述符
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4-140
官方文档方法描述符:
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.3.3
开始分析字节码:
二字符串拼接的优化
m1()方法源码中是使用+号拼接,但是在字节码中也被编译成了 StringBuilder方式
三其他优化
3.1尽量使用局部变量
调用方法时传递的参数以及在调用中创建的临时变量都保存在栈中速度快
其他变量(静态变量,实例变量)在堆中,创建速度慢
栈中的变量随着方法的运行结束不需要额外的垃圾回收
3.2减少对同一变量的反复计算
for (int i = 0; i < list.size(); i++) {…}
替换为:
int length = list.size();
for (int i = 0, i < length; i++){…}
3.3、尽量采用懒加载的策略
String str = “aaa”;
if (i == 1){
list.add(str);
}
//建议替换成
if (i == 1){
String str = “aaa”;
list.add(str);
}
3.4、异常不应该用来控制程序流程
首先
异常会创建一个新对象
其次
异常是一个重量级对象,
异常需要收集整个方法调用的栈
3.5、不要将数组声明为public static final
3.6、不要创建一些不使用的对象,不要导入一些不使用的 类
3.7、程序运行过程中避免使用反射
反射很强大但是性能不高(Method的invoke方法)
一种建议性的做法是将那些需要通过反射加载的类在项目启动的时候 通过反射实例化出一个对象并放入内存。
3.8、使用数据库连接池和线程池
3.9、容器初始化时尽可能指定长度
3.10、ArrayList随机遍历快,LinkedList添加删除快
https://blog.csdn.net/qq_50695280/article/details/114376412
3.11、使用Entry遍历Map
Map<String,String> map = new HashMap<>();
for (Map.Entry<String,String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
}
这样只遍历一次下面有keySet()是遍历2次
Map<String,String> map = new HashMap<>();
for (String key : map.keySet()) {
String value = map.get(key);
}
3.12、不要手动调用System.gc()
3.13少使用正则
3.14日志输出级别
当前日志是error
LOGGER.info(“错误了”+user)
3.15、对资源的close()建议分开操作