当前位置: 首页 > news >正文

java 字节码分析_java字节码文件分析

痛痛快快来分析一下java字节码文件:

源文件:

public class Person {

private String name;

public void walk(){

System.out.println("I am walking.");

}

}

对应16进制表示:

986ea56f5c6c744256ddfdfb469682ac.gif

CA FE BA BE 00 00 00 33 00 21 07 00 02 01 00 06 50 65 72 73 6F 6E 07 00 04 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74 01 00 04 6E 61 6D 65 01 00 12 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 06 3C 69 6E 69 74 3E 01 00 03 28 29 56 01 00 04 43 6F 64 65 0A 00 03 00 0B 0C 00 07 00 08 01 00 0F 4C 69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65 01 00 12 4C 6F 63 61 6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00 04 74 68 69 73 01 00 08 4C 50 65 72 73 6F 6E 3B 01 00 04 77 61 6C 6B 09 00 12 00 14 07 00 13 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 53 79 73 74 65 6D 0C 00 15 00 16 01 00 03 6F 75 74 01 00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 3B 08 00 18 01 00 0D 49 20 61 6D 20 77 61 6C 6B 69 6E 67 2E 0A 00 1A 00 1C 07 00 1B 01 00 13 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 0C 00 1D 00 1E 01 00 07 70 72 69 6E 74 6C 6E 01 00 15 28 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00 0A 53 6F 75 72 63 65 46 69 6C 65 01 00 0B 50 65 72 73 6F 6E 2E 6A 61 76 61 00 21 00 01 00 03 00 00 00 01 00 02 00 05 00 06 00 00 00 02 00 01 00 07 00 08 00 01 00 09 00 00 00 2F 00 01 00 01 00 00 00 05 2A B7 00 0A B1 00 00 00 02 00 0C 00 00 00 06 00 01 00 00 00 02 00 0D 00 00 00 0C 00 01 00 00 00 05 00 0E 00 0F 00 00 00 01 00 10 00 08 00 01 00 09 00 00 00 37 00 02 00 01 00 00 00 09 B2 00 11 12 17 B6 00 19 B1 00 00 00 02 00 0C 00 00 00 0A 00 02 00 00 00 06 00 08 00 07 00 0D 00 00 00 0C 00 01 00 00 00 09 00 0E 00 0F 00 00 00 01 00 1F 00 00 00 02 00 20

class文件规范格式应为:

ClassFile {

u4 magic;

u2 minor_version;

u2 major_version;

u2 constant_pool_count;

cp_info constant_pool[constant_pool_count-1];

u2 access_flags;

u2 this_class;

u2 super_class;

u2 interfaces_count;

u2 interfaces[interfaces_count];

u2 fields_count;

field_info fields[fields_count];

u2 methods_count;

method_info methods[methods_count];

u2 attributes_count;

attribute_info attributes[attributes_count];

}

字节码分析:(u1表示1个字节, u2表示2个字节,依次类推...)

CA FE BA BE // 标识该文件为.class文件[u4];

00 00 00 33 // 标识jdk编译版本: 小版本[u2] 大版本[u2], 这里大版本为51, 说明该文件由jdk7编译而来;

00 21 // 标识该class文件的常量池个数[u2], 说明该文件有33个常量项

java7规范中常量池中常量项的类型有(常量项索引从1开始计数, 记住每一种常量类型都有各自的结构):

Constant Type

Value

CONSTANT_Class

7

CONSTANT_Fieldref

9

CONSTANT_Methodref

10

CONSTANT_InterfaceMethodref

11

CONSTANT_String

8

CONSTANT_Integer

3

CONSTANT_Float

4

CONSTANT_Long

5

CONSTANT_Double

6

CONSTANT_NameAndType

12

CONSTANT_Utf8

1

CONSTANT_MethodHandle

15

CONSTANT_MethodType

16

CONSTANT_InvokeDynamic

18

先分析常量池:

第1个常量:

07 00 02

07 // 07 表示该常量为CONSTANT_Class类型的常量,我们看看CONTSTANT_Class类型常量的结构:

CONSTANT_Class:{

u1: 标志(07)

u2: 常量池索引,上面这个例子 [00 02] 说明指向的就是第2个常量项,再继续看第2个常量项:即Person

}

第2个常量:

01 00 06 50 65 72 73 6F 6E

01 // 表示该常量为CONSTANT_Utf8类型的常量类型,CONSTANT_Utf8常量类型结构为:

CONSTANT_Uft8:{

u1: 标志(01)

u2: 字符串长度, [00 06]表示这个字符串占6个字节

u[int[u2]]: 表示第三部分的长度由u2值决定,这里是50 65 72 73 6F 6E, 这6个字节对应的ASCII码就是Person, 明白了吧

}

第3个常量:

07 00 04

07 //CONSTANT_Class常量类型,且其字符串指向第4(00 04)个常量,即java/lang/Object

第4个常量:

01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74

01 //CONSTAT_Utf8常量类型,且长度为16[00 10], 紧跟的16个字节为6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74, 就是java/lang/Object

第5个常量:

01 00 04 6E 61 6D 65

01 //CONSTANT_Utf8

00 04 //4个字节长度

6E 61 6D 65 --> name

第6个常量:

01 00 12 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B

01 //CONSTANT_Utf8

00 12 //18个字节长度

// 4C 6A ... 67 3B --> Ljava/lang/String;

第7个常量:

01 00 06 3C 69 6E 69 74 3E

01 //CONSTANT_Utf8

00 06 //6个字节长度

3C 69 6E 69 74 3E --> 第8个常量:

01 00 03 28 29 56

01 //CONSTANT_Utf8

00 03 //3个字节

28 29 56 --> ()V

第9个常量:

01 00 04 43 6F 64 65

01 //CONSTANT_Utf8

00 04 //4个字节

43 6F 64 65 --> Code 第10个常量:

0A 00 03 00 0B

0A // CONSTANT_Methodref

CONSTANT_Methodref {

u1(11) 标志

u2 指向方法所属类的描述符CONSTANT_Utf8的索引项

u2 指向方法名称及类型描述符CONSTANT_NameAndType的索引项

}

00 03 //第3个常量:如前面的,为java/lang/Object这个超类

00 0B //第11个常量:根据第11个常量:为方法

第11个常量:

0C 00 07 00 08

0C //CONSTANT_NameAndType

CONSTANT_NameAndType结构:

{

u1(12) 标志

u2 指向字段或方法名称的常量项索引

u2 指向字段或方法描述符的常量索引

}

00 07 //第7个常量:

00 08 //第8个常量: ()V

就是指类实例的初始化方法

第12个常量:

01 00 0F 4C 69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65 //CONSTANT_Utf8 15字节 LineNumberTable

第13个常量:

01 00 12 4C 6F 63 61 6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 //CONSTANT_Utf8 18字节 LocalVariableTable

第14个常量:

01 00 04 74 68 69 73 //CONSTANT_Utf8 4字节 this

第15个常量:

01 00 08 4C 50 65 72 73 6F 6E 3B //CONSTANT_Utf8 8字节 LPerson;

第16个常量:

01 00 04 77 61 6C 6B //CONSTANT_Utf8 4字节 walk

第17个常量:

09 00 12 00 14

09 //CONSTANT_Fieldref

CONSTANT_Fieldref结构:

{

u1(9) 标志

u2 指向字段所属类或接口描述符CONSTANT_Class的索引项

u2 指向字段描述符CONSTANT_NameAndType的索引项

}

00 12 //第18个常量:即java/lang/System

00 14 //第20个常量:out Ljava/io/PrintStream;

第18个常量:

07 00 13 //CONSTANT_Class 指向第19(00 13)个常量:即java/lang/System

第19个常量:

01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 53 79 73 74 65 6D //CONSTANT_Utf8 16个字节 java/lang/System

第20个常量:

0C 00 15 00 16 //CONSTANT_NameAndType 第21(00 15)个常量:out 第22(00 16)个常量:Ljava/io/PrintStream;

第21个常量:

01 00 03 6F 75 74 //CONSTANT_Utf8 3字节 out

第22个常量:

01 00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 3B //CONSTANT_Utf8 21字节 Ljava/io/PrintStream;

第23个常量:

08 00 18

08 //CONSTANT_String

CONSTANT_String常量类型结构:

{

u1(08) 标志

u2 指向字符串字面量的索引

}

00 18 //第24个常量:I am walking.

第24个常量:

01 00 0D 49 20 61 6D 20 77 61 6C 6B 69 6E 67 2E //CONSTANT_Utf8 13(00 0D)字节 I am walking.

第25个常量:

0A 00 1A 00 1C //CONSTANT_Methodref 第26(00 1A)个常量:java/lang/PrintStream 第28(00 1C)个常量:println (Ljava/lang/String;)V

第26个常量:

07 00 1B //CONSTANT_Class 第27(00 1B)个常量: java/lang/PrintStream

第27个常量:

01 00 13 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74 53 74 72 65 61 6D //CONSTANT_Utf8 19(00 13)字节 java/lang/PrintStream

第28个常量:

0C 00 1D 00 1E //CONSTANT_NameAndType 第29(1D)个常量: println 第30(00 1E)个常量: (Ljava/lang/String;)V

第29个常量:

01 00 07 70 72 69 6E 74 6C 6E //CONSTANT_Utf8 7字节 println

第30个常量:

01 00 15 28 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 //CONSTANT_Utf8 21(00 15)字节 (Ljava/lang/String;)V

第31个常量:

01 00 0A 53 6F 75 72 63 65 46 69 6C 65 //CONSTANT_Utf8 10(00 0A)字节 SourceFile

第32个常量:

01 00 0B 50 65 72 73 6F 6E 2E 6A 61 76 61 //CONSTANT_Utf8 11(00 0B)字节 Person.java

第33个常量:null

终于结束常量池的解析,进入到其他内容解析:

access_flags 表示该类或接口的访问属性

访问属性有:

ACC_PUBLIC

0x0001

Declared public; may be accessed from outside its package.

ACC_FINAL

0x0010

Declared final; no subclasses allowed.

ACC_SUPER

0x0020

Treat superclass methods specially when invoked by the invokespecial instruction.

ACC_INTERFACE

0x0200

Is an interface, not a class.

ACC_ABSTRACT

0x0400

Declared abstract; must not be instantiated.

ACC_SYNTHETIC

0x1000

Declared synthetic; not present in the source code.

ACC_ANNOTATION

0x2000

Declared as an annotation type.

ACC_ENUM

0x4000

Declared as an enum type.

00 21 // 即ACC_PUBLIC | ACC_SUPER, 确实符合Person类的访问属性,ACC_SUPER指是否允许使用invokespecial指令, jdk1.2后编译出的class文件的该标志均为true

this_class

00 01 //指向CONSTANT_Class常量类型的索引,即第1个常量:Person

super_class

00 03 //指向CONSTANT_Class常量类型的索引,即第3个常量:java/lang/Object

开始解析接口表:

interfaces_count

00 00 //0, 确实我们的Person没有实现接口

interfaces(无,因为上面interfaces_count为0,如果有接口,则该属性为 [u2 u2 ..], 表示各接口对应的常量池中的索引项,且类型为CONSTANT_Class)

接口表解析完成。

开始解析字段表:

fields_count

00 01 //只有1个字段

field_info,这是属性域结构,其结构为:

{

u2: access_flags //访问标志

u2: name_index //对应字段名称,指向常量池索引,类型为CONSTANT_Utf8

u2: descriptor_index //对应字段描述符,指向常量池索引, 类型为CONSTANT_Utf8

u2: atrributes_count //字段的属性个数

attribute_info //属性信息,也具有自己的结构,后面遇到再讲

} 字段的访问标志有这些:

Flag Name

Value

Interpretation

ACC_PUBLIC

0x0001

Declared public; may be accessed from outside its package.

ACC_PRIVATE

0x0002

Declared private; usable only within the defining class.

ACC_PROTECTED

0x0004

Declared protected; may be accessed within subclasses.

ACC_STATIC

0x0008

Declared static.

ACC_FINAL

0x0010

Declared final; never directly assigned to after object construction (JLS §17.5).

ACC_VOLATILE

0x0040

Declared volatile; cannot be cached.

ACC_TRANSIENT

0x0080

Declared transient; not written or read by a persistent object manager.

ACC_SYNTHETIC

0x1000

Declared synthetic; not present in the source code.

ACC_ENUM

0x4000

Declared as an element of an enum.

00 02 // 对应ACC_PRIVATE 私有域

00 05 // 字段的名称,看上面第5个常量,即name

00 06 // 字段的描述符,看上面第6个常量,即Ljava/lang/String;

00 00 // 0个属性,即该字段没有额外属性,但是也得说下attribute的结构

//attribute的结构:

{

u2: attribute_name_index //属性名称,指向常量池索引,类型为CONSTANT_Utf8

u4: attribute_length //属性长度

u1: info //具体属性信息,长度就是attribute_length

}

// 如果有多个属性,就按其结构顺序排列下去,这里name字段没有属性,下面就是方法属性等的分析了

字段表解析完毕。

开始解析方法表:

methods_count 方法个数

00 02 // 该类有2个方法

method_info, 方法信息

{ //有得说method_info结构了,其实和field_info是一样的,只是access_flags取值范围不一样

u2: access_flags //访问标志

u2: name_index //对应方法名称,指向常量池索引,类型为CONSTANT_Utf8

u2: descriptor_index //对应方法描述符,指向常量池索引, 类型为CONSTANT_Utf8

u2: atrributes_count //方法的属性个数

attribute_info //属性信息,同上

} 方法的访问标志表:

Flag Name

Value

Interpretation

ACC_PUBLIC

0x0001

Declared public; may be accessed from outside its package.

ACC_PRIVATE

0x0002

Declared private; accessible only within the defining class.

ACC_PROTECTED

0x0004

Declared protected; may be accessed within subclasses.

ACC_STATIC

0x0008

Declared static.

ACC_FINAL

0x0010

Declared final; must not be overridden (§5.4.5).

ACC_SYNCHRONIZED

0x0020

Declared synchronized; invocation is wrapped by a monitor use.

ACC_BRIDGE

0x0040

A bridge method, generated by the compiler.

ACC_VARARGS

0x0080

Declared with variable number of arguments.

ACC_NATIVE

0x0100

Declared native; implemented in a language other than Java.

ACC_ABSTRACT

0x0400

Declared abstract; no implementation is provided.

ACC_STRICT

0x0800

Declared strictfp; floating-point mode is FP-strict.

ACC_SYNTHETIC

0x1000

Declared synthetic; not present in the source code.

这里讲一下属性的种类,后面分析得比较多:

Attribute

Section

Java SE

class file

ConstantValue

1.0.2

45.3

Code

1.0.2

45.3

StackMapTable

6

50.0

Exceptions

1.0.2

45.3

InnerClasses

1.1

45.3

EnclosingMethod

5.0

49.0

Synthetic

1.1

45.3

Signature

5.0

49.0

SourceFile

1.0.2

45.3

SourceDebugExtension

5.0

49.0

LineNumberTable

1.0.2

45.3

LocalVariableTable

1.0.2

45.3

LocalVariableTypeTable

5.0

49.0

Deprecated

1.1

45.3

RuntimeVisibleAnnotations

5.0

49.0

RuntimeInvisibleAnnotations

5.0

49.0

RuntimeVisibleParameterAnnotations

5.0

49.0

RuntimeInvisibleParameterAnnotations

5.0

49.0

AnnotationDefault

5.0

49.0

BootstrapMethods

7

51.0

第1个方法解析:

00 01 // 对应ACC_PUBLIC, 即该方法为public

00 07 // 方法名称,看第7个常量,即方法,构造器方法

00 08 // 方法描述符,看第8个常量,即()V

00 01 // 方法有1个属性

00 09 // 该属性名称是第9个常量,即Code, 当然我们每个方法确实要有Code才行,哪怕是空的

Code是属性的一种,它也有自己的结构:

{

u2 attribute_name_index; //指向常量池索引,但其实字节码中并没有其值,固定为Code

u4 attribute_length;

u2 max_stack; //栈最大深度

u2 max_locals; //方法局部变量使用的最大空间,单位为Slot, 每个Slot可存放32位的数据类型,除long,double占2个Slot外,其余基本类型都占1个Slot

u4 code_length; //方法字节码指令长度,1个指令占1个字节,因为jvm至今只有200来个字节码指令,1个字节可表示256种指令

u1 code[code_length]; //对应的字节码指令序列,jvm栈是基于栈的指令操作,大多数指令都是单字节指令,但是也有多字节指令,如[invokespecial u2],其后面2个字节指向常量池索引的CONSTANT_Methodref类型的常量

u2 exception_table_length; //异常表长度,下面是异常表结构

{ u2 start_pc;

u2 end_pc;

u2 handler_pc;

u2 catch_type;

} exception_table[exception_table_length]; //各个异常

u2 attributes_count; //属性个数

attribute_info attributes[attributes_count]; //各属性

}

00 00 00 2F attribute_length为37,之所以没有attribute_name_index,其实这里已经固定为Code了,没必要再占2个字节去指向常量池

00 01 //栈最大深度为1

00 01 //局部变量最大空间为1Slot

00 00 00 05 // 指令集长度为5

2A B7 00 0A B1 查看字节码指令集可知: 2A(aload_0,将第一个引用类型(this)本地变量推送至栈顶) B7(invokespecial, 调用超类构造方法,实例初始化方法或私有方法,后2个字节00 0A指向常量池索引,即java/lang/Object., B1(return))

00 00 // 异常表为0,所以下面就没有异常信息了,直接就attributes_count了

00 02 // 2个属性

解析第1个属性:

00 0C //指向第12个常量,即LineNumberTable, LineNumberTable也有自己的结构:

// LineNumberTable结构

{

u2 attribute_name_index; //同Code属性一致,固定为LineNumberTable, 所以字节码里也没有为其保留位置

u4 attribute_length;

u2 line_number_table_length; //下面是行号表结构

{ u2 start_pc; // 字节码行号(偏移量)

u2 line_number; // 源码行号

} line_number_table[line_number_table_length];

}

00 00 00 06 // attribute_length属性长度为6, 记住没有attribute_name_index的字节码,否则是多余

00 01 // 有1个行号表

00 00 // 字节码行号:0

00 02 // 源码行号:2

再解析第2个属性:

00 0D // 看第13个常量,即LocalVariableTable局部表量表,LocalVariableTable也是一种属性,其结构为:

// 局部变量表结构:

{

u2 attribute_name_index; //同理不占字节,固定为LocalVariableTable

u4 attribute_length;

u2 local_variable_table_length; //局部变量与当前栈帧的关系结构

{ u2 start_pc; // 局部变量起始偏移量

u2 length; //局部变量作用范围长度

u2 name_index; //局部变量名称,指向常量池索引

u2 descriptor_index; //局部变量描述符,指向常量池索引

u2 index; //所在局部变量数组的索引位置, 如果为long或double在index和index+1

} local_variable_table[local_variable_table_length];

}

00 00 00 0C attrbute_length为12

00 01 // 有一个局部变量与当前栈帧的关系

00 00 // 起始偏移0

00 05 // 作用范围长度为5

00 0E // 名称指向14个常量,即this

00 0F // 描述指向第15个常量,即LPerson;

00 00 // 即为局部变量数组的第0个

解析第2个方法walk:

00 01 //访问属性为public

00 10 //方法名称,第16个常量,即walk

00 08 //方法描述符,第8个常量,即()V

00 01 //属性个数为1

解析该属性:

00 09 //指向第9个常量,即Code

00 00 00 37 //attribute_length为45

00 02 //最大的栈深度为2

00 01 //最大局部变量Slot数为1

00 00 00 09 //代码长度9

B2 00 11 //B2:getstatic 00 11:第17个常量,即System.out的引用放到栈顶

12 17 //12:ldc 讲第23个常量(int, float, 或者String字面量的引用)放到栈顶,即将I am walking.的引用放到栈顶

B6 00 19 //B6:invokevirtual调用实例方法,这里就是println

B1 //B1:return方法返回

00 00 //没有异常表

00 02 //有2个属性

第1个属性LineNumberTable:

00 0C // 第12个常量,即LineNumberTable

00 00 00 0A //属性长度为10

00 02 //有2个行号表

00 00 00 06 00 08 00 07 //2个行号表分别为:0:6 8:7

第2个属性LocalVariableTable:

00 0D //属性类型为LocalVariableTable

00 00 00 0C //属性长度为12

00 01 //有1个局部变量

00 00 //该变量偏移量为0

00 09 //该变量作用范围长度为9

00 0E //该变量名称指向第14个常量,即this

00 0F //该变量描述符指向第15个常量 ,即LPerson;

00 00 //该变量在局部变量数组的第0个位置

到此方法表解析完毕。

下面就是类的属性表了:

00 01 //有1属性

00 1F //属性类型指向第31个常量,即SourceFile

{//SourceFile结构

u2 attribute_name_index; //固定为SourceFile

u4 attribute_length; //属性长度

u2 sourcefile_index; //源文件名称,指向常量池索引

}

00 00 00 02 //属性长度为2

00 20 //源文件名称指向第32个常量,即Person.java

类的属性表解析完毕。

到此整个class文件解析完成,还有一些属性没有体现出来这里,可以自己去试试。

不吝指正。

相关文章:

  • java的反射注解_Java中的注解和反射
  • mfc将mysql查询结果取出_笔记-mysql 导出查询结果
  • mysql数据库中的各种约束_数据库Mysql的学习(三)-各种约束
  • java linux磁盘_java获取linux的磁盘空间,磁盘利用率
  • eclipse java转maven_关于在eclipse中使用Maven创建项目转换成javaweb步骤
  • uwp连接mysql数据库_[UWP小白日记-11]在UWP中使用Entity Framework Core(Entity Framework 7)操作SQLite数据库(一)...
  • centos apache php mysql zend_Centos6.5+php+apache+mysql+zendguardloader环境安装
  • java =1 ==1_为什么在Java中-1右移1 = -1?
  • java commons-pool_apache commons-pool的配置参数
  • JAVA CP936编码转utf8_Java编码转换 - querychinesesto的个人空间 - OSCHINA - 中文开源技术交流社区...
  • java hssffont_Java HSSFFont.setBoldweight方法代碼示例
  • java怎样创建字符串列表_java第三季lt;6-5gt;:生成随机字符串列表并排序之实现...
  • java多表return语句吗_java – 需要一个return语句吗? – 新编码
  • java网格布局如何为空_Java 网格布局
  • java 反序列化php对象_Java对对象的序列化和反序列化
  • php的引用
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • .pyc 想到的一些问题
  • 【跃迁之路】【699天】程序员高效学习方法论探索系列(实验阶段456-2019.1.19)...
  • 〔开发系列〕一次关于小程序开发的深度总结
  • Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包
  • docker python 配置
  • Java 最常见的 200+ 面试题:面试必备
  • Laravel Telescope:优雅的应用调试工具
  • SpringBoot 实战 (三) | 配置文件详解
  • Tornado学习笔记(1)
  • vue自定义指令实现v-tap插件
  • Webpack入门之遇到的那些坑,系列示例Demo
  • 浮动相关
  • 基于Volley网络库实现加载多种网络图片(包括GIF动态图片、圆形图片、普通图片)...
  • 记一次和乔布斯合作最难忘的经历
  • 理解 C# 泛型接口中的协变与逆变(抗变)
  • 利用jquery编写加法运算验证码
  • 少走弯路,给Java 1~5 年程序员的建议
  • 使用Swoole加速Laravel(正式环境中)
  • 学习JavaScript数据结构与算法 — 树
  • 学习Vue.js的五个小例子
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • !!java web学习笔记(一到五)
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • ( 用例图)定义了系统的功能需求,它是从系统的外部看系统功能,并不描述系统内部对功能的具体实现
  • (06)金属布线——为半导体注入生命的连接
  • (C#)一个最简单的链表类
  • (C语言)fgets与fputs函数详解
  • (delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)
  • (pytorch进阶之路)扩散概率模型
  • (附源码)ssm户外用品商城 毕业设计 112346
  • (附源码)基于ssm的模具配件账单管理系统 毕业设计 081848
  • (转)关于pipe()的详细解析
  • .Mobi域名介绍
  • .NET Core 2.1路线图
  • .net framework 4.0中如何 输出 form 的name属性。
  • .NET Standard 的管理策略
  • .NetCore 如何动态路由