admin 2025-05-19 13:23:16 世界杯明星球员

Java代码执行顺序

Java代码执行顺序

1. Java初步认知2. Javayun.java例子3. 反编译Javayun.class文件4. 分析Javayun_dxdump文件5. 再来一个网上的例子JavaTest.java6. 查看一下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是常量池,是对象构造函数、是类初始化函数

reading Javayun.class...

begin classfile

magic: cafebabe

minor_version: 0000

major_version: 0034

constant_pool_count: 003b

constant_pool:

0001: method{java.lang.Object.:()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{""}

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{""}

0020: utf8{"SourceFile"}

0021: utf8{"Javayun.java"}

0022: nat{:()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: 0004

fields[0]:

access_flags: private

name: a1

descriptor: I

attributes_count: 0000

end fields[0]

fields[1]:

access_flags: private|static

name: a2

descriptor: I

attributes_count: 0000

end fields[1]

fields[2]:

access_flags: private

name: a3

descriptor: I

attributes_count: 0000

end fields[2]

fields[3]:

access_flags: private|static

name: a4

descriptor: I

attributes_count: 0000

end fields[3]

methods_count: 0004

methods[0]:

access_flags: public

name:

descriptor: ()V

attributes_count: 0001

attributes[0]:

name: Code

length: 00000037

max_stack: 0002

max_locals: 0001

code_length: 00000017

0000: aload_0 // 00

0001: invokespecial method{java.lang.Object.:()V}

0004: aload_0 // 00

0005: ldc string{"Log private int a1"}

0007: invokestatic method{Javayun.JavaPrintln:(Ljava/lang/String;)I}

000a: putfield field{Javayun.a1:I}

000d: aload_0 // 00

000e: ldc string{"Log private int a3"}

0010: invokestatic method{Javayun.JavaPrintln:(Ljava/lang/String;)I}

0013: putfield field{Javayun.a3:I}

0016: return

exception_table_length: 0000

attributes_count: 0001

attributes[0]:

name: LineNumberTable

length: 0000000e

line_number_table_length: 0003

0000 1

0004 8

000d 16

end attributes[0]

end attributes[0]

end methods[0]

methods[1]:

access_flags: public|static

name: JavaPrintln

descriptor: (Ljava/lang/String;)I

attributes_count: 0001

attributes[0]:

name: Code

length: 00000027

max_stack: 0002

max_locals: 0001

code_length: 0000000b

0000: getstatic field{java.lang.System.out:Ljava/io/PrintStream;}

0003: aload_0 // 00

0004: invokevirtual method{java.io.PrintStream.println:(Ljava/lang/String;)

V}

0007: sipush #+01f4

000a: ireturn

exception_table_length: 0000

attributes_count: 0001

attributes[0]:

name: LineNumberTable

length: 0000000a

line_number_table_length: 0002

0000 4

0007 5

end attributes[0]

end attributes[0]

end methods[1]

methods[2]:

access_flags: public|static

name: main

descriptor: ([Ljava/lang/String;)V

attributes_count: 0001

attributes[0]:

name: Code

length: 00000025

max_stack: 0002

max_locals: 0001

code_length: 00000009

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: return

exception_table_length: 0000

attributes_count: 0001

attributes[0]:

name: LineNumberTable

length: 0000000a

line_number_table_length: 0002

0000 25

0008 26

end attributes[0]

end attributes[0]

end methods[2]

methods[3]:

access_flags: static

name:

descriptor: ()V

attributes_count: 0001

attributes[0]:

name: Code

length: 00000049

max_stack: 0002

max_locals: 0000

code_length: 00000021

0000: 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: return

exception_table_length: 0000

attributes_count: 0001

attributes[0]:

name: LineNumberTable

length: 00000016

line_number_table_length: 0005

0000 10

0008 13

0010 18

0018 21

0020 22

end attributes[0]

end attributes[0]

end methods[3]

attributes_count: 0001

attributes[0]:

name: SourceFile

length: 00000002

source: string{"Javayun.java"}

end attributes[0]

end classfile

4. 分析Javayun_dxdump文件

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

methods[3]:

//静态方法

access_flags: static

//名字叫

name:

//()括号里面代表参数,里面没有内容,代表没有参数,返回值是V也就是void,没有内容

descriptor: ()V

//这个字段里面有一个属性

attributes_count: 0001

//第一个属性

attributes[0]:

//代码

name: Code

length: 00000049

max_stack: 0002

max_locals: 0000

code_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 a2

0000: 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.println

0008: 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: return

exception_table_length: 0000

attributes_count: 0001

attributes[0]:

name: LineNumberTable

length: 00000016

line_number_table_length: 0005

0000 10

0008 13

0010 18

0018 21

0020 22

end 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

//方法名字是main

name: main

//参数是"java/lang/String"字符串的"["数组,返回值是void

descriptor: ([Ljava/lang/String;)V

//这个字段里面有一个属性

attributes_count: 0001

attributes[0]:

name: Code

length: 00000025

max_stack: 0002

max_locals: 0001

code_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: return

exception_table_length: 0000

attributes_count: 0001

attributes[0]:

name: LineNumberTable

length: 0000000a

line_number_table_length: 0002

0000 25

0008 26

end 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|static

name: JavaPrintln

descriptor: (Ljava/lang/String;)I

attributes_count: 0001

attributes[0]:

name: Code

length: 00000027

max_stack: 0002

max_locals: 0001

code_length: 0000000b

//获取print方法

0000: getstatic field{java.lang.System.out:Ljava/io/PrintStream;}

//aload_0在静态方法里面代表方法的第一个参数,这里是"String i"

0003: aload_0 // 00

//打印日志,传入的是操作数aload_0

0004: 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: ireturn

exception_table_length: 0000

attributes_count: 0001

attributes[0]:

name: LineNumberTable

length: 0000000a

line_number_table_length: 0002

0000 4

0007 5

end attributes[0]

end attributes[0]

end methods[1]

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

methods[0]:

access_flags: public

name:

descriptor: ()V

attributes_count: 0001

attributes[0]:

name: Code

length: 00000037

max_stack: 0002

max_locals: 0001

code_length: 00000017

//在非静态函数里面aload_0代表:载入this到操作数栈aload_0中

0000: aload_0 // 00

//调用this的Object.方法

0001: invokespecial method{java.lang.Object.:()V}

//载入this到操作数栈aload_0中,不然找不到类普通变量a1

0004: 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 // 00

000e: ldc string{"Log private int a3"}

0010: invokestatic method{Javayun.JavaPrintln:(Ljava/lang/String;)I}

0013: putfield field{Javayun.a3:I}

//返回

0016: return

exception_table_length: 0000

attributes_count: 0001

attributes[0]:

name: LineNumberTable

length: 0000000e

line_number_table_length: 0003

0000 1

0004 8

000d 16

end 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;

}

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

public class JavaTest {

//8. main函数在类初始化之后才会执行

public static void main(String[] args){

//9. main函数调用f1()

f1();

}

//1. 第一个执行的地方,不过这里会调用构造函数

static JavaTest javaTest = new JavaTest();

static {

//6. 第二个执行的地方

System.out.println("1");

}

//2. 属于对象构造,会先初始化,这里是非静态代码块优先级和非静态成员变量一样,谁在前面谁先执行

{

System.out.println("2");

}

JavaTest(){

//4. 执行构造函数里面方法

System.out.println("3");

//5. a=100, b=0 (注意了,静态变量b还没有初始化,

//目前还在第一个执行的地方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. 第三个执行的地方

static int b = 200;

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

2 3 a=100, b=0 1 4

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

1、一样是开始

methods[3]:

access_flags: static

name:

descriptor: ()V

attributes_count: 0001

attributes[0]:

name: Code

length: 00000039

max_stack: 0002

max_locals: 0000

code_length: 00000019

//新建一个JavaTest对象

0000: new type{JavaTest}

//将JavaTest 2次压入栈中,dup复制栈顶。相当于把操作数栈顶元素pop出来,再把它push两次

0003: dup

//调用JavaTest的构造函数

0004: invokespecial method{JavaTest.:()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 #+00c8

0015: putstatic field{JavaTest.b:I}

//返回

0018: return

exception_table_length: 0000

attributes_count: 0001

attributes[0]:

name: LineNumberTable

length: 0000000e

line_number_table_length: 0003

0000 7

000a 10

0012 27

end attributes[0]

end attributes[0]

end methods[3]

attributes_count: 0001

2、中调用了构造函数

methods[1]:

access_flags: 0000

name:

descriptor: ()V

attributes_count: 0001

attributes[0]:

name: Code

length: 0000006e

max_stack: 0003

max_locals: 0001

code_length: 00000042

//Object.初始化

0000: aload_0 // 00

0001: invokespecial method{java.lang.Object.:()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 // 00

000d: bipush #+64

000f: 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.

0021: invokespecial method{java.lang.StringBuilder.:()V}

//载入"a="到栈中

0024: ldc string{"a="}

//将"a="放入StringBuilder.append

0026: invokevirtual method{java.lang.StringBuilder.append:(Ljava/lang/Strin

g;)Ljava/lang/StringBuilder;}

//载入this到栈中

0029: aload_0 // 00

//获取非静态变量int a

002a: getfield field{JavaTest.a:I}

//将非静态变量int a放入StringBuilder.append

002d: invokevirtual method{java.lang.StringBuilder.append:(I)Ljava/lang/Str

ingBuilder;}

//载入"b="到栈中,并放入StringBuilder.append

0030: ldc string{", b="}

0032: invokevirtual method{java.lang.StringBuilder.append:(Ljava/lang/Strin

g;)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/Str

ingBuilder;}

//调用StringBuilder.toString并打印日志

003b: invokevirtual method{java.lang.StringBuilder.toString:()Ljava/lang/St

ring;}

003e: invokevirtual method{java.io.PrintStream.println:(Ljava/lang/String;)

V}

//返回

0041: return

exception_table_length: 0000

attributes_count: 0001

attributes[0]:

name: LineNumberTable

length: 0000001a

line_number_table_length: 0006

0000 17

0004 14

000c 26

0012 18

001a 19

0041 20

end attributes[0]

end attributes[0]

end methods[1]

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

methods[0]:

access_flags: public|static

name: main

descriptor: ([Ljava/lang/String;)V

attributes_count: 0001

attributes[0]:

name: Code

length: 00000020

max_stack: 0000

max_locals: 0001

code_length: 00000004

//调用静态函数public static void f1(),这里也不需要this

0000: invokestatic method{JavaTest.f1:()V}

0003: return

exception_table_length: 0000

attributes_count: 0001

attributes[0]:

name: LineNumberTable

length: 0000000a

line_number_table_length: 0002

0000 4

0003 5

end attributes[0]

end attributes[0]

end methods[0]

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

methods[2]:

access_flags: public|static

name: f1

descriptor: ()V

attributes_count: 0001

attributes[0]:

name: Code

length: 00000025

max_stack: 0002

max_locals: 0000

code_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: return

exception_table_length: 0000

attributes_count: 0001

attributes[0]:

name: LineNumberTable

length: 0000000a

line_number_table_length: 0002

0000 23

0008 24

end attributes[0]

end attributes[0]

end methods[2]

7. 总结一下

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

1、 是类初始化函数,会第一个运行(Android Zyogte的类提前加载preloaded-classes使用的方法就是) 2、 静态变量和静态代码块会在里面初始化,静态方法是按需调用,不是一定会跑的 3、 静态变量和静态代码块的优先级是一样的,谁写在前面就谁先运行 4、 类对象构造函数,不一定会运行 5、类对象构造函数第一个跑的是Object的init对象构造函数(注意了Object是父类) 6、 非静态变量和非静态代码块会在里面初始化 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代码的执行顺序了吧,不再是书本上的似是而非的东西, 这里只是入门指引,大家有兴趣可以基于此持续研究学习

Copyright © 2088 世界杯金靴奖_2014年巴西世界杯预选赛 - omdzds.com All Rights Reserved.
友情链接