Java代码执行顺序

  • 1. Java初步认知
  • 2. Javayun.java例子
  • 3. 反编译Javayun.class文件
  • 4. 分析Javayun_dxdump文件
  • 5. 再来一个网上的例子JavaTest.java
  • 6. 查看一下JavaTest的反编译数据
  • 7. 总结一下

1. Java初步认知

大家对于Java的执行顺序应该都有一定了解,起码书本上或者印象中有一点了解,
如静态变量、普通变量、类、静态函数、静态代码块、构造函数应该都知道和会用。

这次就讲一下Java入门的基础内容(眼见为实,而且加证明过程,贴答案不算):clint函数、init函数、main函数

2. Javayun.java例子

Javayun.java这个例子的代码如下:里面有main函数,静态变量、类变量、静态函数、静态代码块

public class Javayun {public static int JavaPrintln(String i) {System.out.println(i);return 500;
}private int a1 = JavaPrintln("Log private int a1");private static int a2 = JavaPrintln("Log private static int a2");static {System.out.println("static code b1");
}private int a3 = JavaPrintln("Log private int a3");private static int a4 = JavaPrintln("Log private static int a4");static {System.out.println("static code b2");
}public static void main(String[] args) {System.out.println("main fuction");
}}

猜测:
1、印象中静态变量属于类,应该先初始化
2、然后静态代码块应该也会初始化吧
3、静态变量、静态代码的顺序,不是特别清楚,可能写在前面就是先初始化吧
4、main函数是java应用程序的入口函数会跑
5、运行java的时候,需要这个对象吗?不是很清楚
6、它们的执行顺序不是清楚,入口是main函数,main函数之前应该也有代码在跑吧?
从上面的java代码无法得到我们想要的全部内容

我们直接看执行结果(注意运行结果并不能直接厘清我们的疑惑,没看到代码的运行过程不能算解惑,大家先初步看看即可,别太关注,后面还是看编译后的代码):

E:\demo>javac Javayun.java
E:\demo>java Javayun
Log private static int a2 //执行静态变量a2
static code b1 //执行静态代码块b1
Log private static int a4 //执行静态变量a4
static code b2 //执行静态代码块b2
main fuction //执行main函数

得到的结论有哪些(仍有疑惑,这是直接看答案,过程呢…)?
1、静态变量和静态代码块的优先级是一样的,谁写在前面就谁先运行
2、main函数确实有在跑,不过肯定不是第一个运行的代码
3、类的普通变量a1、a3,没有运行,代表类对象没有创建,也就是类的构造函数在java main函数运行的时候可以不跑

3. 反编译Javayun.class文件

在输入E:\demo>javac Javayun.java的时候可以在当前目录看到还有一个Javayun.class文件生成。
直接反编译解析一下这个文件。
(.class文件是java编译生成的二进制文件,可以在任何java虚拟机(JVM)中运行,和平台无关, 加载器是Class Loader)

这里提供2中方法:

1、使用java的原生指令:javap -v -p JavaTest.class > JavaTest_javap
2、使用Android SDK提供的工具:D:\tools\SDK\build-tools\30.0.0\dx.bat --dump JavaTest.class > JavaTest_dxdump

这里先以2为例子讲解一下:
打开2中的JavaTest_dxdump文件
一看这个代码就有点长了(也先不看,可以跳过直接看下一章,这里全部贴出来主要是为了部分回头看的同学准备的),constant_pool是常量池,<init>是对象构造函数、<clinit>是类初始化函数

reading Javayun.class...
begin classfile
magic: cafebabe
minor_version: 0000
major_version: 0034
constant_pool_count: 003bconstant_pool:0001: method{java.lang.Object.<init>:()V}0002: string{"Log private int a1"}0003: method{Javayun.JavaPrintln:(Ljava/lang/String;)I}0004: field{Javayun.a1:I}0005: string{"Log private int a3"}0006: field{Javayun.a3:I}0007: field{java.lang.System.out:Ljava/io/PrintStream;}0008: method{java.io.PrintStream.println:(Ljava/lang/String;)V}0009: string{"main fuction"}000a: string{"Log private static int a2"}000b: field{Javayun.a2:I}000c: string{"static code b1"}000d: string{"Log private static int a4"}000e: field{Javayun.a4:I}000f: string{"static code b2"}0010: type{Javayun}0011: type{java.lang.Object}0012: utf8{"a1"}0013: utf8{"I"}0014: utf8{"a2"}0015: utf8{"a3"}0016: utf8{"a4"}0017: utf8{"<init>"}0018: utf8{"()V"}0019: utf8{"Code"}001a: utf8{"LineNumberTable"}001b: utf8{"JavaPrintln"}001c: utf8{"(Ljava/lang/String;)I"}001d: utf8{"main"}001e: utf8{"([Ljava/lang/String;)V"}001f: utf8{"<clinit>"}0020: utf8{"SourceFile"}0021: utf8{"Javayun.java"}0022: nat{<init>:()V}0023: utf8{"Log private int a1"}0024: nat{JavaPrintln:(Ljava/lang/String;)I}0025: nat{a1:I}0026: utf8{"Log private int a3"}0027: nat{a3:I}0028: type{java.lang.System}0029: nat{out:Ljava/io/PrintStream;}002a: type{java.io.PrintStream}002b: nat{println:(Ljava/lang/String;)V}002c: utf8{"main fuction"}002d: utf8{"Log private static int a2"}002e: nat{a2:I}002f: utf8{"static code b1"}0030: utf8{"Log private static int a4"}0031: nat{a4:I}0032: utf8{"static code b2"}0033: utf8{"Javayun"}0034: utf8{"java/lang/Object"}0035: utf8{"java/lang/System"}0036: utf8{"out"}0037: utf8{"Ljava/io/PrintStream;"}0038: utf8{"java/io/PrintStream"}0039: utf8{"println"}003a: utf8{"(Ljava/lang/String;)V"}
end constant_pool
access_flags: public|super
this_class: type{Javayun}
super_class: type{java.lang.Object}
interfaces_count: 0000
fields_count: 0004fields[0]:access_flags: privatename: a1descriptor: Iattributes_count: 0000
end fields[0]fields[1]:access_flags: private|staticname: a2descriptor: Iattributes_count: 0000
end fields[1]fields[2]:access_flags: privatename: a3descriptor: Iattributes_count: 0000
end fields[2]fields[3]:access_flags: private|staticname: a4descriptor: Iattributes_count: 0000
end fields[3]
methods_count: 0004methods[0]:access_flags: publicname: <init>descriptor: ()Vattributes_count: 0001attributes[0]:name: Codelength: 00000037max_stack: 0002max_locals: 0001code_length: 000000170000: aload_0 // 000001: invokespecial method{java.lang.Object.<init>:()V}0004: aload_0 // 000005: ldc string{"Log private int a1"}0007: invokestatic method{Javayun.JavaPrintln:(Ljava/lang/String;)I}000a: putfield field{Javayun.a1:I}000d: aload_0 // 00000e: ldc string{"Log private int a3"}0010: invokestatic method{Javayun.JavaPrintln:(Ljava/lang/String;)I}0013: putfield field{Javayun.a3:I}0016: returnexception_table_length: 0000attributes_count: 0001attributes[0]:name: LineNumberTablelength: 0000000eline_number_table_length: 00030000 10004 8000d 16end attributes[0]end attributes[0]
end methods[0]methods[1]:access_flags: public|staticname: JavaPrintlndescriptor: (Ljava/lang/String;)Iattributes_count: 0001attributes[0]:name: Codelength: 00000027max_stack: 0002max_locals: 0001code_length: 0000000b0000: getstatic field{java.lang.System.out:Ljava/io/PrintStream;}0003: aload_0 // 000004: invokevirtual method{java.io.PrintStream.println:(Ljava/lang/String;)V}0007: sipush #+01f4000a: ireturnexception_table_length: 0000attributes_count: 0001attributes[0]:name: LineNumberTablelength: 0000000aline_number_table_length: 00020000 40007 5end attributes[0]end attributes[0]
end methods[1]methods[2]:access_flags: public|staticname: maindescriptor: ([Ljava/lang/String;)Vattributes_count: 0001attributes[0]:name: Codelength: 00000025max_stack: 0002max_locals: 0001code_length: 000000090000: getstatic field{java.lang.System.out:Ljava/io/PrintStream;}0003: ldc string{"main fuction"}0005: invokevirtual method{java.io.PrintStream.println:(Ljava/lang/String;)V}0008: returnexception_table_length: 0000attributes_count: 0001attributes[0]:name: LineNumberTablelength: 0000000aline_number_table_length: 00020000 250008 26end attributes[0]end attributes[0]
end methods[2]methods[3]:access_flags: staticname: <clinit>descriptor: ()Vattributes_count: 0001attributes[0]:name: Codelength: 00000049max_stack: 0002max_locals: 0000code_length: 000000210000: ldc string{"Log private static int a2"}0002: invokestatic method{Javayun.JavaPrintln:(Ljava/lang/String;)I}0005: putstatic field{Javayun.a2:I}0008: getstatic field{java.lang.System.out:Ljava/io/PrintStream;}000b: ldc string{"static code b1"}000d: invokevirtual method{java.io.PrintStream.println:(Ljava/lang/String;)V}0010: ldc string{"Log private static int a4"}0012: invokestatic method{Javayun.JavaPrintln:(Ljava/lang/String;)I}0015: putstatic field{Javayun.a4:I}0018: getstatic field{java.lang.System.out:Ljava/io/PrintStream;}001b: ldc string{"static code b2"}001d: invokevirtual method{java.io.PrintStream.println:(Ljava/lang/String;)V}0020: returnexception_table_length: 0000attributes_count: 0001attributes[0]:name: LineNumberTablelength: 00000016line_number_table_length: 00050000 100008 130010 180018 210020 22end attributes[0]end attributes[0]
end methods[3]
attributes_count: 0001attributes[0]:name: SourceFilelength: 00000002source: string{"Javayun.java"}
end attributes[0]
end classfile

4. 分析Javayun_dxdump文件

1、先来看一下<clinit>函数:类的初始化函数,只要使用这个类,都需要进入这个函数

methods[3]://静态方法access_flags: static//名字叫<clinit>name: <clinit>//()括号里面代表参数,里面没有内容,代表没有参数,返回值是V也就是void,没有内容descriptor: ()V//这个字段里面有一个属性attributes_count: 0001//第一个属性attributes[0]://代码name: Codelength: 00000049max_stack: 0002max_locals: 0000code_length: 00000021//载入"Log private static int a2"到栈中//上面还有2句话,000a中string字段:对应CONSTANT_String_info的tag,指向002d(javap解析出来是#45)//000a: string{"Log private static int a2"} => #10 = String             #45//002d中utf8字段:对应CONSTANT_String_info的string_index,这里被初始化为Log private static int a2//002d: utf8{"Log private static int a2"} => #45 = Utf8               Log private static int a20000: ldc string{"Log private static int a2"}//调用JavaPrintln方法,打印日志,传入的参数是上面载入栈中的"Log private static int a2"0002: invokestatic method{Javayun.JavaPrintln:(Ljava/lang/String;)I}//将返回值赋值给静态变量a2 => 到这里走完了private static int a2 = JavaPrintln("Log private static int a2");0005: putstatic field{Javayun.a2:I}//获取打印日志的静态方法System.out.println0008: getstatic field{java.lang.System.out:Ljava/io/PrintStream;}//将"static code b1"入栈000b: ldc string{"static code b1"}//打印日志 => 到这里执行完了System.out.println("static code b1");000d: invokevirtual method{java.io.PrintStream.println:(Ljava/lang/String;)V}//执行静态变量初始化private static int a2 = JavaPrintln("Log private static int a2");0010: ldc string{"Log private static int a4"}0012: invokestatic method{Javayun.JavaPrintln:(Ljava/lang/String;)I}0015: putstatic field{Javayun.a4:I}//执行静态代码块System.out.println("static code b2");0018: getstatic field{java.lang.System.out:Ljava/io/PrintStream;}001b: ldc string{"static code b2"}001d: invokevirtual method{java.io.PrintStream.println:(Ljava/lang/String;)V}//返回了0020: returnexception_table_length: 0000attributes_count: 0001attributes[0]:name: LineNumberTablelength: 00000016line_number_table_length: 00050000 100008 130010 180018 210020 22end attributes[0]end attributes[0]
end methods[3]

那么按顺序目前跑了下面的代码

private static int a2 = JavaPrintln("Log private static int a2");static {System.out.println("static code b1");
}private static int a4 = JavaPrintln("Log private static int a4");static {System.out.println("static code b2");
}

输出

Log private static int a2 //执行静态变量a2
static code b1 //执行静态代码块b1
Log private static int a4 //执行静态变量a4
static code b2 //执行静态代码块b2

2、接着看一下main,java程序的入口函数,运行java程序就会跑
(注意Android中不是每一个类都会有main函数,这里只有一个类,那就只能这个类跑main函数)

methods[2]://静态方法,而且是public的access_flags: public|static//方法名字是mainname: main//参数是"java/lang/String"字符串的"["数组,返回值是voiddescriptor: ([Ljava/lang/String;)V//这个字段里面有一个属性attributes_count: 0001attributes[0]:name: Codelength: 00000025max_stack: 0002max_locals: 0001code_length: 00000009//打印日志System.out.println("main fuction");0000: getstatic field{java.lang.System.out:Ljava/io/PrintStream;}0003: ldc string{"main fuction"}0005: invokevirtual method{java.io.PrintStream.println:(Ljava/lang/String;)V}0008: returnexception_table_length: 0000attributes_count: 0001attributes[0]:name: LineNumberTablelength: 0000000aline_number_table_length: 00020000 250008 26end attributes[0]end attributes[0]
end methods[2]

到目前为止输出的是,程序已经执行完了,
可以看到确实没有跑类对象构造函数以及普通变量的初始化也没用进行,
静态变量和静态代码块的优先级是一样的,谁写在前面就谁先运行

Log private static int a2 //执行静态变量a2
static code b1 //执行静态代码块b1
Log private static int a4 //执行静态变量a4
static code b2 //执行静态代码块b2
main fuction //执行main函数

3、类中的其他方法

=> JavaPrintln静态函数

methods[1]:access_flags: public|staticname: JavaPrintlndescriptor: (Ljava/lang/String;)Iattributes_count: 0001attributes[0]:name: Codelength: 00000027max_stack: 0002max_locals: 0001code_length: 0000000b//获取print方法0000: getstatic field{java.lang.System.out:Ljava/io/PrintStream;}//aload_0在静态方法里面代表方法的第一个参数,这里是"String i"0003: aload_0 // 00//打印日志,传入的是操作数aload_00004: invokevirtual method{java.io.PrintStream.println:(Ljava/lang/String;)V}//常量压入栈中,#+01f4是500//当int取值-1~5采用iconst指令,取值-128~127采用bipush指令,取值-32768~32767采用sipush指令,//取值-2147483648~2147483647采用 ldc 指令0007: sipush #+01f4//返回,返回值是i(int整型)000a: ireturnexception_table_length: 0000attributes_count: 0001attributes[0]:name: LineNumberTablelength: 0000000aline_number_table_length: 00020000 40007 5end attributes[0]end attributes[0]
end methods[1]

=> 构造函数,如果使用javap会显示为"public Javayun()",由于这里没有构造函数,会自动生成一个
看一下对象构造函数会做什么事情

methods[0]:access_flags: publicname: <init>descriptor: ()Vattributes_count: 0001attributes[0]:name: Codelength: 00000037max_stack: 0002max_locals: 0001code_length: 00000017//在非静态函数里面aload_0代表:载入this到操作数栈aload_0中0000: aload_0 // 00//调用this的Object.<init>方法0001: invokespecial method{java.lang.Object.<init>:()V}//载入this到操作数栈aload_0中,不然找不到类普通变量a10004: aload_0 // 00//将"Log private int a1"压入栈0005: ldc string{"Log private int a1"}//调用打印函数0007: invokestatic method{Javayun.JavaPrintln:(Ljava/lang/String;)I}//将返回值赋值给类普通变量a1 => 到这里执行完了private int a1 = JavaPrintln("Log private int a1");000a: putfield field{Javayun.a1:I}//执行private int a3 = JavaPrintln("Log private int a3");000d: aload_0 // 00000e: ldc string{"Log private int a3"}0010: invokestatic method{Javayun.JavaPrintln:(Ljava/lang/String;)I}0013: putfield field{Javayun.a3:I}//返回0016: returnexception_table_length: 0000attributes_count: 0001attributes[0]:name: LineNumberTablelength: 0000000eline_number_table_length: 00030000 10004 8000d 16end attributes[0]end attributes[0]
end methods[0]

5. 再来一个网上的例子JavaTest.java

1、JavaTest具体代码如下(网上的其实也是只公布了答案,没看到具体的代码运行过程,所以这里就挑选来讲一讲)

public class JavaTest {public static void main(String[] args){f1();}static JavaTest javaTest = new JavaTest();static {System.out.println("1");}{System.out.println("2");}JavaTest(){System.out.println("3");System.out.println("a=" + a + ", b=" + b);}public static void f1(){System.out.println("4");}int a = 100;static int b = 200;
}

从之前的例子我们其实可以大概知道这里的执行顺序,
<clinit>函数是先执行的,然后main函数最后也会执行

public class JavaTest {//8. main函数在<clinit>类初始化之后才会执行public static void main(String[] args){//9. main函数调用f1()f1();}//1. <clinit>第一个执行的地方,不过这里会调用构造函数<init>static JavaTest javaTest = new JavaTest();static {//6. <clinit>第二个执行的地方System.out.println("1");}//2. 属于对象构造,会先初始化,这里是非静态代码块优先级和非静态成员变量一样,谁在前面谁先执行{System.out.println("2");}JavaTest(){//4. 执行构造函数里面方法System.out.println("3");//5. a=100, b=0 (注意了,静态变量b还没有初始化,//目前还在<clinit>第一个执行的地方static JavaTest javaTest = new JavaTest())System.out.println("a=" + a + ", b=" + b);}public static void f1(){//10. f1()执行System.out.println("4");}//3. 属于对象构造,初始化非静态成员变量int a = 100;//7. <clinit>第三个执行的地方static int b = 200;

运行结果是,和上面描述的顺序是一致的,这里再得到一个信息,
类的构造函数会先将非静态成员初始化,然后再执行我们写入构造函数的方法(这里是由于本例子中重新写了构造函数,并在里面加了内容)

2
3
a=100, b=0
1
4

6. 查看一下JavaTest的反编译数据

1、一样是<clinit>开始

methods[3]:access_flags: staticname: <clinit>descriptor: ()Vattributes_count: 0001attributes[0]:name: Codelength: 00000039max_stack: 0002max_locals: 0000code_length: 00000019//新建一个JavaTest对象0000: new type{JavaTest}//将JavaTest 2次压入栈中,dup复制栈顶。相当于把操作数栈顶元素pop出来,再把它push两次0003: dup//调用JavaTest的构造函数0004: invokespecial method{JavaTest.<init>:()V}//赋值给静态变量javaTest => 此处跑完了static JavaTest javaTest = new JavaTest();0007: putstatic field{JavaTest.javaTest:LJavaTest;}//初始化静态代码块System.out.println("1");000a: getstatic field{java.lang.System.out:Ljava/io/PrintStream;}000d: ldc string{"1"}000f: invokevirtual method{java.io.PrintStream.println:(Ljava/lang/String;)V}//初始化静态变量static int b = 200; sipush是将#+00c8(200)压入栈中0012: sipush #+00c80015: putstatic field{JavaTest.b:I}//返回0018: returnexception_table_length: 0000attributes_count: 0001attributes[0]:name: LineNumberTablelength: 0000000eline_number_table_length: 00030000 7000a 100012 27end attributes[0]end attributes[0]
end methods[3]
attributes_count: 0001

2、<clinit>中调用了<init>构造函数

methods[1]:access_flags: 0000name: <init>descriptor: ()Vattributes_count: 0001attributes[0]:name: Codelength: 0000006emax_stack: 0003max_locals: 0001code_length: 00000042//Object.<init>初始化0000: aload_0 // 000001: invokespecial method{java.lang.Object.<init>:()V}//初始化非静态代码块System.out.println("2");0004: getstatic field{java.lang.System.out:Ljava/io/PrintStream;}0007: ldc string{"2"}0009: invokevirtual method{java.io.PrintStream.println:(Ljava/lang/String;)V}//初始化非静态变量int a = 100;000c: aload_0 // 00000d: bipush #+64000f: putfield field{JavaTest.a:I}//运行自定义构造函数里面的内容System.out.println("3");0012: getstatic field{java.lang.System.out:Ljava/io/PrintStream;}0015: ldc string{"3"}0017: invokevirtual method{java.io.PrintStream.println:(Ljava/lang/String;)V}//运行自定义构造函数里面的内容System.out.println("a=" + a + ", b=" + b);//获取System.out.println方法001a: getstatic field{java.lang.System.out:Ljava/io/PrintStream;}//新建一个StringBuilder对象001d: new type{java.lang.StringBuilder}//StringBuilder对象在栈中一共压入了2次0020: dup//StringBuilder对象消耗了一次,用于StringBuilder.<init>0021: invokespecial method{java.lang.StringBuilder.<init>:()V}//载入"a="到栈中0024: ldc string{"a="}//将"a="放入StringBuilder.append0026: invokevirtual method{java.lang.StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;}//载入this到栈中0029: aload_0 // 00//获取非静态变量int a002a: getfield field{JavaTest.a:I}//将非静态变量int a放入StringBuilder.append002d: invokevirtual method{java.lang.StringBuilder.append:(I)Ljava/lang/StringBuilder;}//载入"b="到栈中,并放入StringBuilder.append0030: ldc string{", b="}0032: invokevirtual method{java.lang.StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;}//获取静态变量static int b(注意这里不需要this指针),并放入StringBuilder.append//到目前为止b是没有内容的,也就是默认是0,还没有初始化0035: getstatic field{JavaTest.b:I}0038: invokevirtual method{java.lang.StringBuilder.append:(I)Ljava/lang/StringBuilder;}//调用StringBuilder.toString并打印日志003b: invokevirtual method{java.lang.StringBuilder.toString:()Ljava/lang/String;}003e: invokevirtual method{java.io.PrintStream.println:(Ljava/lang/String;)V}//返回0041: returnexception_table_length: 0000attributes_count: 0001attributes[0]:name: LineNumberTablelength: 0000001aline_number_table_length: 00060000 170004 14000c 260012 18001a 190041 20end attributes[0]end attributes[0]
end methods[1]

3、在函数执行完后,会执行main函数,java程序入口函数

methods[0]:access_flags: public|staticname: maindescriptor: ([Ljava/lang/String;)Vattributes_count: 0001attributes[0]:name: Codelength: 00000020max_stack: 0000max_locals: 0001code_length: 00000004//调用静态函数public static void f1(),这里也不需要this0000: invokestatic method{JavaTest.f1:()V}0003: returnexception_table_length: 0000attributes_count: 0001attributes[0]:name: LineNumberTablelength: 0000000aline_number_table_length: 00020000 40003 5end attributes[0]end attributes[0]
end methods[0]

4、其它函数public static void f1()

methods[2]:access_flags: public|staticname: f1descriptor: ()Vattributes_count: 0001attributes[0]:name: Codelength: 00000025max_stack: 0002max_locals: 0000code_length: 00000009//执行System.out.println("4");0000: getstatic field{java.lang.System.out:Ljava/io/PrintStream;}0003: ldc string{"4"}0005: invokevirtual method{java.io.PrintStream.println:(Ljava/lang/String;)V}0008: returnexception_table_length: 0000attributes_count: 0001attributes[0]:name: LineNumberTablelength: 0000000aline_number_table_length: 00020000 230008 24end attributes[0]end attributes[0]
end methods[2]

7. 总结一下

从上面我们知道的一些java的基础知识

1、 <clinit>是类初始化函数,会第一个运行(Android Zyogte的类提前加载preloaded-classes使用的方法就是<clinit>)
2、 静态变量和静态代码块会在<clinit>里面初始化,静态方法是按需调用,不是一定会跑的
3、 静态变量和静态代码块的优先级是一样的,谁写在前面就谁先运行
4、 <init>类对象构造函数,不一定会运行
5、<init>类对象构造函数第一个跑的是Object的init对象构造函数(注意了Object是父类)
6、 非静态变量和非静态代码块会在<init>里面初始化
7、 非静态变量和非静态代码块的优先级是一样的,谁写在前面就谁先运行
8、 非静态变量是在自定义构造函数代码之前会初始化
9、 main函数:java程序入口函数,运行java程序会执行(但是不是每个class都有,
Android的class如Activity.class就没有这个函数,程序入口只需要一个,不需要每个类都有)

使用的方法有:

1、使用java的原生指令:javap -v -p JavaTest.class > JavaTest_javap
2、使用Android SDK提供的工具:D:\tools\SDK\build-tools\30.0.0\dx.bat --dump JavaTest.class > JavaTest_dxdump

其它情况,如jar包和apk里面看class的内容,也是类似,这里将反编译方法写在下面:
如果你是jar包,可以反编译出来(效果类似于dx --dump)

java -jar apktool.jar d + 路径

如果是apk,可以使用下面反编译查看

./apktool d ***.apk

到这里大家应该清楚java代码的执行顺序了吧,不再是书本上的似是而非的东西,
这里只是入门指引,大家有兴趣可以基于此持续研究学习

Java代码执行顺序相关推荐

  1. Java基础之代码执行顺序深入解析

    Java基础之代码执行顺序深入解析 结合实例代码分析: public class demo6 {public static void main(String[] args) {new Son();Sy ...

  2. java 执行顺序_Java代码执行顺序

    程序中代码执行的顺序非常重要,稍有不慎便会是程序运行出错,那么我将结合实例来分析代码中的执行. 名词解释 首先了解几个名词: 非静态代码块 直接由 { } 包起来的代码,称为非静态代码块 静态代码块 ...

  3. day9 java的实例语句块和代码执行顺序

    实例语句块 每执行一次构造就会在前执行一次实例语句块 代码执行顺序

  4. day9 java的静态代码块和代码执行顺序

    静态代码块 代码执行顺序 对于静态,不管是变量还是代码块.都是自上而下的.

  5. 【Linux 内核 内存管理】RCU 机制 ④ ( RCU 模式下更新链表项 list_replace_rcu 函数 | 链表操作时使用 smp_wmb() 函数保证代码执行顺序 )

    文章目录 一.RCU 模式下更新链表项 list_replace_rcu 函数 二.链表操作时使用 smp_wmb() 函数保证代码执行顺序 一.RCU 模式下更新链表项 list_replace_r ...

  6. java build path entries 为空_TOOLFK工具-在线JAVA代码执行工具

    本文要推荐的[TOOLFK]在线JAVA代码执行工具 ,提供JAVA代码在线执行功能. 網站名稱:ToolFk 網站鏈結:https://www.toolfk.com/ 工具链接:https://ww ...

  7. python装饰器调用顺序_聊一聊Python装饰器的代码执行顺序

    为什么写这篇文章? 起因是QQ群里边有人提了一个问题:之前导入模块只需要1~2秒,为什么现在变成需要2~3分钟? 我的第一感觉是:是不是导入的模块顶层代码里边,做了什么耗时的事情.隔了一天,他的问题解 ...

  8. java解析shell命令_Android中执行java命令的方法及java代码执行并解析shell命令

    这篇文章给大家介绍Android中执行java命令的方法及java代码执行并解析shell命令,需要的朋友一起学习 android中执行java命令的方法大家都晓得吗,下面一段内容给大家带来了具体解析 ...

  9. java 调用wget_通过命令行执行WGET下载会更快,而通过Java代码执行时会更慢

    我正在使用WGET通过java代码下载文件,这需要大约10分钟才能下载20 MB文件.但是通过命令行执行wget下载,同样的文件以10MbPs的速度在7秒内下载.有人知道为什么吗?我该如何改进我的Ja ...

最新文章

  1. python用途与前景-Python就业前景如何?三大就业岗位分享
  2. 解决wps与matlab不兼容的问题
  3. 深圳腾讯java小星星_腾讯自研沙盒手游《手工星球》邀你共赴星派对,来CJ现场一起嗨!...
  4. try{}里有一个 return 语句,那么紧跟在这个 try 后的 finally {}里的 code 会 不会被执行,什么时候被执行,在 return 前还是后?...
  5. Java在ACM中的应用
  6. Qt工作笔记-QVector与QMap查找效率实战
  7. linux批量重命名脚本,Linux批量命名文件SH脚本整理
  8. [导入]MsAjax Lib- Date.parseInvariant 函数
  9. 再见,Python!你好,Go语言\n\n
  10. Adober Pro DC 破
  11. Maven项目中父子项目互相找不到的解决方法
  12. Python入门的学习心得
  13. 使用 Colab 训练 Pytorch-Yolov4 (WongKinYiu版)
  14. CODEVS 2853 方格游戏
  15. 【云原生 · Docker】入门篇:安装、镜像加速
  16. python打不开py文件查看代码,用python打开py文件
  17. 三个可长期发展的网络副业,稳定的兼职渠道,不再为网络做苦力
  18. win10突然无法显示图片缩略图怎么办
  19. linux关闭ipv6dns,dns关闭ipv6
  20. DataGrip连接MySQL报错: Server returns invalid timezone. Go to ‘Advanced‘ tab and set ‘serverTimezon

热门文章

  1. 微信与企业微信开启debugx5
  2. 3DMax基础骨架绑定教程
  3. 西门子数控单元维修NCU730.3BPN 6FC5373-0AA30-0AB0
  4. 计算机毕业设计(附源码)python中草药管理系统
  5. 社区团购小程序需要服务器吗,为什么说社区团购小程序和团购电商模式结合很有必要!...
  6. 特别好用的前端html富文本编辑器wangEditor个人使用案例
  7. 苹果“变质”,换道变现为何广招嫌弃?
  8. 武汉大学计算机2017博士录取,通知公告 | 2017年博士拟录取名单公示及相关说明...
  9. 即时通讯技术的架构设计
  10. QReader:Chrome 浏览器上的二维码阅读器