文章目录
一、字节码文件
二、Java注解
字节码文件中保存了源代码编译之后的内容,以二进制的方式存储,无法直接用记事本打开阅读。通过NotePad++使用十六进制插件查看class文件:
推荐使用jclasslib
工具查看字节码文件。Github地址:
https://github.com/ingokegel/jclasslib
选择右侧的Releases发行版本,下载对应安装包,傻瓜式安装。
字节码文件中常量池的作用:避免相同的内容重复定义,节省空间。
iconst_常量值
。将常量0放入操作数栈istore_数组下标
。从操作数栈取出放入局部变量表1号位置(操作栈数据弹出、放入局部变量表,栈中数据没有了)iload_数组下标
。将局部变量表1中的数据放入操作数栈(将局部变量表中的数据复制了1份、再放到操作数栈中,两边数据都有)通过jclasslib打开字节码文件,查看Code的LocalVariableTable
iconst_常量值
。将常量0放入操作数栈istore_数组下标
。从操作数栈取出放入局部变量表1号位置(操作栈数据弹出、放入局部变量表,栈中数据没有了)iload_数组下标
。将局部变量表1中的数据放入操作数栈(将局部变量表中的数据复制了1份、再放到操作数栈中,两边数据都有)i=i++的执行流程:
i=++i的执行流程:(与i=i++
的区别,iinc 1 by 1
指令在iload_1
之前)
int i = 0;
i = i++;
最终i的值是多少?
答案是0.我通过分析字节码指令发现,i++
先把0取出来放入临时的操作数栈中;接下来对i进行加1,i变成了1;最后再将之前保存的临时值0放入i,最后i就变成了0。
问题:通过字节码指令分析下面三种”加一“的操作性能的高低?(一般字节码越长,操作性能越低)
public class Demo3 {
public static void main(String[] args) {
int i=0, j=0, k=0;
i++;
j = j + 1;
k += 1;
}
}
0 iconst_0
1 istore_1
2 iconst_0
3 istore_2
4 iconst_0
5 istore_3
6 iinc 1 by 1
9 iload_2
10 iconst_1
11 iadd
12 istore_2
13 iinc 3 by 1
16 return
1)javap -v命令
javap -v 字节码文件名称
查看具体的字节码信息(如果jar包需要先使用jar -xvf xxx.jar
命令解压)。将字节码信息放到一个文件中,javap -v path/User.class > /path1/User.txt
2)jclasslib插件
3)阿里arthas(阿尔萨斯)
https://arthas.aliyun.com/doc/
Arthas命令列表:详情可查看 https://arthas.aliyun.com/doc/commands.html
dashboard -i 2000 -n 3 #查看当前系统的实时数据面板,2s刷新一次、共刷新3次
dump java.lang.String
dump -d D:\practise com.gk.GkApiApplication #将JVM中实际运行的 class 的 byte code dump 到指定目录
jad com.gk.GkApiApplication #反编译指定已加载类的源码
在IDEA@GetMapp("/{id}")
中,点击左侧小气球——>选择Generate request in HTTP Client
,可模拟请求
案例:使用阿里arthas定位线上出现的字节码问题
具体步骤:
java -jar arthas-boot.jar
启动arthas,例如
jad com.gk.GkApiApplication`1)如何查看字节码文件
2)字节码文件的核心组成有哪些
public class PersonServiceTest {
@Test //注解(Annotation)
public void testLogin() {
}
@Test //注解(Annotation)
public void testRegister() {
}
}
注解作用:
在以前看过注解@Override。
除此之外,还需要掌握第三方框架中提供的注解:
比如:Junit
//自定义注解--格式。默认值可以不用写
public @interface 注解名称 {
public 属性类型 属性名() default 默认值; //属性类型:Java支持的数据类型 基本上都支持
}
//自定义注解和使用
@注解名(属性名1=值1,属性名2=值2)
示例:
/**
自定义注解(默认值可以不用写)
*/
public @interface MyAnnoTest1 {
public String name();
public int age();
}
@MyAnnoTest1(name = "wj" , age = 18)
public class MyAnnoDemo1 {
@MyAnnoTest1(name = "wj", age = 18)
String aaa;
String bbb;
@MyAnnoTest1(name = "wj" , age = 18)
public void method1(){
System.out.println("method1方法");
}
public void method2(){
System.out.println("method2方法");
}
}
掌握如何使用已经存在的注解即可。
在以后的实际开发中,注解是使用框架已经提供好的注解。
自定义注解+解析注解(很难的,了解),一般会出现在框架的底层。当以后我们要自己写一个框架的时候,才会用到自定义注解+解析注解。
参考黑马程序员相关视频及文档
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。