Java字节码

2023-05-16

Java最黑科技的玩法就是字节码编程,也就是动态修改或是动态生成 Java 字节码。使用字节码可以玩出很多高级的玩法,最高级的还是在 Java 程序运行时进行字节码修改和代码注入。听起来是不是一些很黑客,也很黑科技的事?是的,这个方式使用 Java 这门静态语言在运行时可以进行各种动态的代码修改,而且可以进行无侵入的编程。
比如,我们不需要在代码中埋点做统计或监控,可以使用这种技术把我们的监控代码直接以字节码的方式注入到别人的代码中,从而实现对实际程序运行情况进行统计和监控。但是要做到这个事,还需要学习一个叫 Java Agent 的技术(可以参考我的这篇文章:Java Agent)。

1、Class类文件的结构

根据 Java 虚拟机规范的规定,Class 文件格式采用一种类似 C 语言结构体的伪结构来存储数据,这种伪结构中只有两种数据类型:无符号数和表
无符号数属于基本的数据类型,以 u1、u2、u4、u8 来分别代表 1 个字节、2 个字节、4个字节和 8 个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或者按照 UTF-8 编码构成字符串值。
是由多个无符号数或者其他表作为数据项构成的复合数据类型,所有表都习惯性地以“_info”结尾。表用于描述有层次关系的复合结构的数据,整个 Class 文件本质上就是一张表,它由下表所示的数据项构成。

类型名称数量描述
u4magic1魔数,占用4个字节,offset 0-3
u2minor_version1次版本号,offset 4-5
u2major_version1主版本号 ,offset 7-8
u2constant_pool_count1常量池数量,offset 8-9
cp_infoconstant_pollconstant_pool_count-1常量池,Class 文件之中的资源仓库。数量不固定
u2access_flags1访问标志,用于识别一些类或者接口层次的访问信息
u2this_class1类索引,用于确定这个类的全限定名
u2super_class1父类索引,用于确定这个类的父类的全限定名
u2interfaces_count1接口计数器,表示索引表的容量
u2interfacesinterfaces_count接口索引集合,用来描述这个类实现了哪些接口
u2fields_count1字段容量计数器,记录这个表含有多少个字段
field_infofieldsfields_count字段表集合,用于描述接口或者类中声明的变量
u2methods_count1方法表计数器,记录这个表含有多少个方法
method_infomethodsmethods_count方法表集合,存放 Class 的方法集合
u2attributes_count1属性表计数器,表示字段表或方法表有多少个属性
attributeattributesattributes_count属性表集合,在 Class 文件、字段表、方法表都可以携带自己的属性表集合,以用于描述某些场景专有的信息

为方便讲解,在这里准备了一段最简单的代码,也希望大家能跟着实际操作一遍:

package org.clazz;

public class TestClazz {
    private int m;

    public int inc() {
        return m + 1;
    }
}

使用 javac 将这个文件转换成 Class,然后用十六进制编辑器 WinHex 打开这个 Class 文件:
在这里插入图片描述
有了以上的知识准备,现在我们一起分析上面的 Class 分别代表什么意思。揭开这层神秘的面纱!

1.1、魔数

每个 Class 文件的头 4 个字节称为魔数(Magic Number),它的唯一作用是确定这个文件是否为一个能被虚拟机接受的 Class 文件。
很多文件存储标准中都使用魔数来进行身份识别,譬如图片格式,如 gif 或者 jpeg 等在文件头中都存有魔数。
文件格式的制定者可以自由地选择魔数值,只要这个魔数值还没有被广泛采用过同时又不会引起混淆即可。
我们看到 TestClazz.class 的魔数也就是头 4 个字节为 CA FE BA BE,用十六进制表示是 0xCAFEBABE(咖啡宝贝?这个名称也太浪漫了吧)。这也意味着每个 Class 文件的魔数值都必须为 0xCAFEBABE。
在这里插入图片描述

1.2、Class 文件的版本

紧接着魔数的 4 个字节存储的是 Class 文件的版本号:5-6 个字节是次版本号(Minor Version),7-8 个字节是主版本号(Major Version)。Java 的版本号是从 45 开始的,JDK 1.1 之后的每个JDK 大版本发布主版本号加 1,高版本的 JDK 能向下兼容以前版本的 Class 文件,但不能运行以后版本的 Class 文件,即使文件格式并未发生任何变化,虚拟机也必须拒绝执行超过起把那本号的 Class 文件。
Class 文件版本号:

JDK版本号10进制版本号16进制版本号
1.145.000 00 00 2D
1.246.000 00 00 2E
1.347.000 00 00 2F
1.448.000 00 00 30
1.549.000 00 00 31
1.650.000 00 00 32
1.751.000 00 00 33
1.852.000 00 00 34

再看看文件对应的值:
在这里插入图片描述
我们看到代表主版本号的 7-8 个字节的值为 0x0034,也即十进制的 52,该版本号说明这个文件是可以被 JDK 1.8 或以上版本虚拟机执行的 Class 文件。

1.3、常量池

紧接着主次版本号之后的是常量池入口,常量池可以理解为 Class 文件之中的资源仓库,它是占用 Class 文件空间最大的数据项目之一。
由于常量池中常量的数量是不固定的,所以在常量池的入口需要放置一项 u2 类型的数据,代表常量池容量计数值(constant_pool_count)。
在这里插入图片描述
如上图所示,常量池容量为十六进制数 0x0016,即十进制的 19,结合上面的 Class 表,我们能知道常量池中有 19 - 1 = 18 项常量。
常量池容量计数值之后就是常量池,常量池中主要存放两大类常量:字面量(Literal)和符号引用(Symbolic References)。
字面量比较接近于 Java 语言层面的常量概念,如文本字符串、声明为 final 的常量值等。
符号引用则属于编译原理方面的概念,包括了下面三类常量:

  • 类和接口的全限定名(Fully Qualified Name)
  • 字段的名称和描述符(Descriptor)
  • 方法的名称和描述符

常量池中每一项常量都是一个表,总共 14 种表:

类型标志描述
CONSTANT_Utf8_info1UTF-8 编码的字符串
CONSTANT_Integer_info3整型字面量
CONSTANT_Float_info4浮点型字面量
CONSTANT_Long5长整型字面量
CONSTANT_Double_info6双精度浮点型字面量
CONSTANT_Class_info7类或接口的符号引用
CONSTANT_String_info8字符串类型字面量
CONSTANT_Fieldref_info9字段的符号引用
CONSTANT_Methidref_info10类中方法的符号引用
CONSTANT_InterfaceMethodref_info11接口中方法的符号引用
CONSTANT_NameAndType_info12字段或方法的部分符号引用
CONSTANT_MethodHandle_info15表示方法句柄
CONSTANT_MethodType_info16标识方法类型
CONSTANT_InvokeDynamic_info18标识一个动态方法调用点

之所以说常量池是最烦琐的数据,是因为这 14 中常量类型各自均有自己的结构。
我们再来看图中常量池的第一项常量,它的标志位(偏移地hi:0x0000000A)是 0x0A,转换为十进制的值为 10,查常量表中对应的标志为 10 的常量属于 CONSTANT_Methodref_info 类型。
在这里插入图片描述
我们看一下 CONSTANT_Methodref_info 类型常量的结构:

名称类型描述
tagu1值为10
indexu2指向声明方法的类描述符 CONSTANT_Class_info 的索引项
indexu2指向名称及类型描述符 CONSTANT_NameAndType 的索引项

上图中的第一个 index 十六进制为 0x0004,即十进制的 4,表示指向常量池中第 4 个常量。
第二个 index 十六进制为 0x000F,即十进制的 15,表示指向常量吃中的第 15 个常量。
(先不管第4、15 常量表示什么)
上面分析的是第一个常量值,接着分析第二个常量值,它的标志位(地址:0x0000000F)是 0x09,即十进制的 9,表示这个常量属于 CONSTANT_Fieldref_info 类型,此常量代表字段的符号引用。
在这里插入图片描述
CONSTANT_Fieldref_info 型常量的结构:

名称类型描述
tagu1值为9
indexu2指向声明字段的类或者接口描述符 CONSTANT_Class_info 的索引项
indexu2指向字段描述符 CONSTANT_NameAndType 的索引项

以上分析了 TestClazz.class 常量池中 18 个常量中的前两个,其余的 16 个依次类推:
在这里插入图片描述
需要注意的是第 18 个常量,tag 标志为 0x01 表示 CONSTANT_Utf8_info :

名称类型描述
tagu1数量 1
lengthu2长度,表示占用几个字节
bytesu1占用 length 个字节

注意 bytes 字段的长度,是根据 length 计算的,length 为 0x0010 转换十进制为 16,所以后面的 bytes 占用 16 个字节。
最后将 14 中常量项的结构定义总结为下表,供大家参考:
在这里插入图片描述

1.4、访问标志

在常量池结束之后,紧接着的两个字节代表访问标志(access_flags),这个标志用于识别一些类或者接口层次的访问信息,包括:这个 Class 是类还是接口;是否定义为 public 类型;是否定义为 abstract 类型;如果是类的话,是否被声明为 final 等。具体标志位以及标志的含义见下表:

标志名称标志值含义
ACC_PUBLIC0x0001是否为 public 类型
ACC_FINAL0x0010是否被声明为 final,只有类可设置
ACC_SUPER0x0020是否允许使用 invokespecial 字节码指令的新语意,invokespecial指令的语意在 JDK 1.0.2 发生过改变,为了区别这条指令使用哪种语意,JDK 1.0.2 之后编译出来的类的这个标志都必须为真
ACC_INTERFACE0x0200标识这是一个接口
ACC_ABSTRACT0x0400是否为 abstract 类型,对于接口或者抽象类来说,此标志值为真,其他类值为假
ACC_SYNTHETIC0x1000标识这个类并非由用户代码产生的
ACC_ANNOTATION0x2000标识这是一个注解
ACC_ENUM0x4000标识这是一个枚举

在这里插入图片描述
TestClazz.class 是一个普通的 java 类,不是接口、枚举,因此它的ACC_PUBLIC、ACC_SUPER标志为真,其他标志为假,因此它的 access_flags 的值为:0x0001|0x0020 = 0x0021。

1.5、类索引、父类索引与接口索引集合

类索引(this_class)和父类索引(super_class)都是一个 u2 类型的数据,而接口索引结合(interfaces)是一组 u2 类型的数据的集合,Class 文件中由这三项数据来确定这个类的继承关系。
类索引和父类索引都是指向一个类型为 CONSTANT_Class_info 的类描述符常量。
在这里插入图片描述
图中看到,TestClazz中的类索引指向的是第 3 个常量,父类索引指向的是第 4 个常量。
对于接口索引集合,入口的第一项——u2 类型的数据为接口计数器(interfaces_count),表示索引表的容量。如果该类没有实现任何接口,则该计数器值为 0 ,后面接口的索引表不再占用任何字节。

1.6、字段表集合

字段表用于描述接口或者类中声明的变量。字段(field)包括类级变量以及实例变量,但不包括在方法内部声明的局部变量。
字段表结构:

类型名称数量
u2access_flags1
u2name_index1
u2descriptor_index1
u2attributes_count1
attribute_infoattributesattributes_count

字段修饰符放在 access_flags 项目中,它与类中的 access_flags 项目是非常类似的,都是一个 u2 的数据类型,其中可以设置的标志位和含义见表:

标志名称标志值含义
ACC_PUBLIC0x0001字段是否为 public
ACC_PRIVATE0x0002字段是否为 private
ACC_PROTECTED0x0004字段是否为 proctected
ACC_STATIC0x0008字段是否为 static
ACC_FINAL0x0010字段是否为 final
ACC_VOLATILE0x0040字段是否为 volatile
ACC_TRANSIENT0x0080字段是否为 transient
ACC_SYNTHETIC0x1000字段是否由编译器自动产生的
ACC_ENUM0x4000字段是否为 enum

跟随 access_flags 标志的是两项索引值:name_index 和 descriptor_index。它们都是对常量池的引用,分别代表着字段的简单名称以及字段和方法的描述符。
在这里插入图片描述

1.7、方法表集合

方法表的内容和字段表几乎采用了完全一致的方式,方法表结构:

类型名称数量
u2access_flags1
u2name_index1
u2descriptor_index1
u2attributes_count1
attribute_infoattributesattributes_count

access_flags 方法访问标志:

标志名称标志值含义
ACC_PUBLIC0x0001方法是否为 public
ACC_PRIVATE0x0002方法是否为 private
ACC_PROTECTED0x0004方法是否为 proctected
ACC_STATIC0x0008方法是否为 static
ACC_FINAL0x0010方法是否为 final
ACC_SYNCHRONIZED0x0020方法是否为 synchronized
ACC_BRIDGE0x0040方法是否是由编译器产生的桥接方法
ACC_VARARGS0x0080方法是否接受不定参数
ACC_NATIVE0x0100方法是否为 native
ACC_ABSTRACT0x0400方法是否为 abstract
ACC_STRICTFP0x0800方法是否为 strictfp
ACC_SYNTHETIC0x1000方法是否由编译器自动产生的

TestClazz对应的位置:
在这里插入图片描述
注意,方法表集合只存放了方法名称,索引等,方法里的代码存放在方法属性表集合中一个名为“Code”的属性里面,这就是下面需要将到的属性表集合。

1.8、属性表集合

属性表(attribute_info)在 Class 文件、字段表、方法表都可以携带自己的属性表集合,以用于描述某些场景专有的信息。
与 Class 文件中其他的数据项目要求严格的顺序、长度和内容不同,属性表集合的限制稍微宽松些,不再要求各个属性表具有严格顺序,并且只要不与已有属性名重复,任何人实现的编译器都可以向属性表中写入自己定义的属性信息,Java 虚拟机运行时会忽略掉它不认识的属性。
虚拟机规范预定义的属性:

属性名称使用位置含义
Code方法表Java 代码编译成的字节码指令
ConstantValue字段表final 关键字定义的常量值
Deprecated类、方法表、字段表被声明为 deprecated 的方法和字段
Exceptions方法表方法抛出的异常
EnclosingMethod类文件仅当一个类为局部类或者匿名类时才能拥有这个属性,这个属性用于标识这个类所在的外围方法
InnerClasses类文件内部类列表
LineNumberTableCode 属性Java 源码的行号与字节码指令的对应关系
LocalVariableTableCode 属性方法的局部变量描述
StackMapTableCode 属性JDK 1.6 中新增的属性,供新的类型检查验证器(Tyoe Checker)检查和处理目标方法的局部变量和操作数栈所需要的类型是否匹配
Signature类、方法表、字段表这个属性用于支持泛型情况下的方法签名,在 Java 语言中,任何类、接口、初始化方法或成员的泛型签名如果包含了类型变量(Type Variables)或参数化类型(Parameterized Types),则 Signature 属性会为它记录泛型签名信息。由于 Java 的泛型采用擦除法实现,在为了避免类型信息被擦除后导致签名混乱,需要这个属性记录泛型中的相关信息
SourceFile类文件记录源文件名称
SourceDebugExtension类文件JDK 1.6 中新增的属性,SourceDebugExtension 属性用于存储额外的调试信息。譬如在进行 JSP 文件调试时,无法通过 Java 堆栈来定位到 JSP 文件的行号,JSR-45 规范为这些非 Java 语言编写,却需要编异常字节码并运行在 Java 虚拟机中的程序提供了一个进行调试的标准机制,使用 SourceDebugExtension 属性就可以用于存储这个标准所新加入的调试信息
Synthetic类、方法表、字段表标识方法或字段为编译器自动生成的
LocalVariableTypeTable它使用特征签名代替描述符,是为了引入泛型语法之后能描述泛型参数化类型而添加
RuntimeVisibleAnnotations类、方法表、字段表为动态注解提供支持。RuntimeVisibleAnnotations 属性用于指明哪些注解是运行时(实际上运行时就是进行反射调用)可见的
RuntimeInvisibleAnnotations类、方法表、字段表与 RuntimeVisibaleAnnotations 属性作用刚好相反,用于指明哪些注解是运行时不可见的
RuntimeVisibleParameterAnnotations方法表作用与 RuntimeVisibleAnnotations 属性类似,只不过作用对象为方法参数
RuntimeInvisibleParameterAnnotations方法表作用与 RuntimeInvisibleAnnotations 属性类似,只不过作用对象为方法参数
AnnotationDefault方法表用于记录注解类元素的默认值
BootstrapMethods类文件JDK 1.7 中新增的属性,用于保存 invokedynamic 指令引用的引导方法限定符

对于每个属性,它的名称需要从常量池中引用一个 CONSTANT_Utf8_info 类型的常量来表示,而属性值的结构则是完全自定义的,只需要通过一个 u4 的长度属性去说明属性值所占用的位数即可,一个符合规则的属性表应该满足下表所定义的结构。
属性表结构:

类型名称数量
u2attribute_name_index1
u4attribute_length1
u1infoattribute_length

1.8.1、Code 属性

Java 程序方法体中的代码经过 Javac 编译器处理后,最终变为字节码指令存储在 Code 属性内。
Code 属性表结构:

类型名称数量描述
u2attibute_name_index1属性名称,指向 CONSTANT_Utf8_info 型常量的索引,常量值固定为“Code”
u4attribute_length1属性值长度,由于属性名称索引与属性长度一共为 6 字节,所以属性值的长度固定为整个属性表长度减去 6 个字节
u2max_stack1操作数栈深度最大值,在方法执行的任意时刻,操作数栈都不会超过这个深度。虚拟机运行的时候需要根据这个值来分配栈帧中的操作栈深度
u2max_locals1局部变量表所需的存储空间,max_locals 的单位是 Slot,Slot 是虚拟机为局部变量分配内存所使用的最小单位
u4code_length1字节码长度
u1codecode_length字节码指令字节流,用于存储字节码指令的一系列字节流。文章的末尾会给出“虚拟机字节码指令表”。
u2exception_table_length1
exception_infoexception_tableexception_table_length
u2attributes_count1
attribute_infoattributesattributes_count

Code 属性是 Class 文件中最重要的一个属性,如果把一个 Java 程序中的信息分为代码(java代码)和元数据(类、字段、方法定义及其他信息)两部分,那么在整个 Class 文件中,Code 属性用于描述代码,所有其他数据项目都用于描述元数据。
继续以 TestClazz.class 文件为例
在这里插入图片描述
它的操作数栈的最大深度和本地变量表的容量都为 0x0001,字节码区域所占空间的长度为 0x0005。
虚拟机读取到字节码长度后,按照顺序依次读入紧随的 5 个字节,并根据字节码指令表翻译出所对应的字节码指令。
翻译 “2A B7 00 0A B1” 的过程:
1.读入 2A,查表得 0x2A 对应得指令为 aload_0,这个指令得含义是将第 0 个 Slot 中为 reference 类型得本地变量推送到操作数栈顶。
2.读入 B7,查表得 0xB7 对应得指令为 invokespecial,这条指令的作用是以栈顶的 reference 类型的数据所指向的对象作为方法接收者,调用此对象的实例构造器方法、private 方法或者它的父类的方法。
3.读入 00 0A,这是 invokespecial 的参数,查常量池得 0x000A 对应的常量为实例构造器“”方法的符号引用。
4.读入 B1,查表得 0xB1 对应得指令为 return,含义是返回此方法,这条指令执行后,当前方法结束。
属性表集合除了 Code 属性,还有 Exceptions 属性、LineNumberTable 属性等等,这里就不一一介绍了。有兴趣得童鞋可以自行了解。

2、javap 工具分析 Class

在 JDK 的 bin 目录中,Oracle 公司已经为我们准备好一个专门用于分析 Class 文件字节码的工具:javap
使用命令:

javap -verbose TestClazz.class

代码清单:

 Last modified 2019-1-14; size 285 bytes
  MD5 checksum c434da45f0fff84f21348a725448f2f5
  Compiled from "TestClazz.java"
public class org.clazz.TestClazz
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #4.#15         // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#16         // org/clazz/TestClazz.m:I
   #3 = Class              #17            // org/clazz/TestClazz
   #4 = Class              #18            // java/lang/Object
   #5 = Utf8               m
   #6 = Utf8               I
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               inc
  #12 = Utf8               ()I
  #13 = Utf8               SourceFile
  #14 = Utf8               TestClazz.java
  #15 = NameAndType        #7:#8          // "<init>":()V
  #16 = NameAndType        #5:#6          // m:I
  #17 = Utf8               org/clazz/TestClazz
  #18 = Utf8               java/lang/Object
{
  public org.clazz.TestClazz();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0

  public int inc();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: getfield      #2                  // Field m:I
         4: iconst_1
         5: iadd
         6: ireturn
      LineNumberTable:
        line 7: 0
}
SourceFile: "TestClazz.java"

结束

到此,相信大家能对字节码有一个较深的认识,Java 语言中的各种变量、关键字和运算符号的语义最终都是由多条字节码命令组合而成的,因此字节码命令所能提供的语义描述能力肯定会比 Java 语言本身更强大。

附录

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java字节码 的相关文章

  • reg52.h中直接定义了P3^4等引脚,但是P1^5引脚没有明确表示出来?

    实际上reg52 h中已经定义了 34 sfr P0 61 0x80 sfr P1 61 0x90 sfr P2 61 0xA0 sfr P3 61 0xB0 34 等引脚的地址 xff0c 如果取P1 5的引脚 xff0c 只需要表示成
  • 关于scanf很多人不知道的小秘密

    今天忽然想到一个问题 xff0c 假如我利用scanf想给变量a输入一个 d的整数 xff0c 结果不小心输入了一个字符串yf或者是123ff后会怎么样呢 xff1f 哈哈 xff0c 自己测试了一下 xff0c 结果发现 xff0c 当你
  • 关于sizeof(*p+1)的那些事

    今天老铁在写程序时发现一个意外 xff0c 在char a 61 1 3 5 7 9 p 61 a 程序求sizeof p 43 1 时遇到一些意外 xff0c 本来以为会是1 xff0c 结果却出意料的是4 xff0c 这就有些尴尬了 x
  • 求解完数

    完数的定义 xff1a 一个数如果恰好等于它的因子之和 xff0c 这个数就称为 完数 例如 xff1a 6 61 1 xff0b 2 xff0b 3 如果需要求解1000或者10000以内的所有完数 xff0c 怎么做呢 xff1f 分析
  • 查找100-200以内素数

    只能被1和其本身整除的数称为素数 xff0c 1不是素数 xff0c 因为简单 xff0c 所以不做解释 xff0c 直接上程序 源代码如下 xff1a Search all prime numbers from 101 to 200 in
  • 实现4个按键控制8个LED灯1个数码管程序

    按要求C语言编程 xff0c 实现4个按键控制8个LED灯1个数码管程序 具体要求如下 xff1a 1 按键一 xff0c 清零作用 无论数码管以前显示何内容 xff0c 都归零 xff0c 显示0 xff1b 2 按键二 xff0c 加一
  • Linux 关机/重启指令

    Linux系统下关机指令只有root用户终端才能下达 xff08 Linux里切换用户可以用 su root 输入密码便进入 root 用户 xff09 xff0c 同时其他终端也会接收到 如root用户发出关机指令 其他终端也会收到相应的
  • C 语言中的goto、 break 和 continue 语句使用

    一 goto 语句 goto 语句为无条件跳转 xff0c goto 语句后面带一个标识符 xff0c 该标识符是同一个函数 内某条语句的标号 标号可以出现在任何可执行语句的前面 xff0c 并且以一个冒号 xff1a 作为后缀 gt Fi
  • 云台控制协议VISCA、PELCO-D、PELCO-P

    原 云台控制协议VISCA PELCO D PELCO P 2013年12月02日 18 42 21 autowanglei 阅读数 xff1a 10146 更多 lt div class 61 34 tags box space 34 g
  • 目录和文件权限与 umask 关系

    一 权限 文件权限 xff1a r xff1a 读取文件内容的权限 w xff1a 新增 修改和删除文件内容的权限 x xff1a 执行文件的权限 例如 xff1a 一个文件a sh xff0c 它的权限是rw xff0c 使用 a sh
  • open 函数的 flag 参数和错误代码

    一 flag 参数 定义头文件 xff1a lt bits fcntl linux h gt 必选参数说明 xff1a define O ACCMODE 0003 xff1a 读写文件操作时取出 flag 的低两位 define O RDO
  • 系统全局变量 errno 是如何获得 errno.h 中的值的呢?

    很多时候我们在使用 errno 的时候都知道它代表的是 errno h 中的错误值 xff0c 可是为什么它就是代表那些值的呢 xff1f 系统在哪里给它赋值了呢 xff1f 故事就要从源头开始 1 errno 全局变量是在哪里定义的 xf
  • const pointer

    int a b const int p 61 a 与int const p 61 a 是一样的 表示p可以指向a xff0c 也可以改变指向b xff0c 但是不能通过指针p来修改a的值 p 61 b p 61 4 int const q
  • I_O —基础概念(参照 Ubuntu 16.04 版本)

    一 文件的概念 定义 xff1a 所谓文件是指一组相关数据的有序集合 xff0c 这个数据集有一个名称 xff0c 叫文件名 如源程序文件 xff0c 目标文件 xff0c 可执行文件 xff0c 头文件等文件通常是在驻留在外部介质上的 x
  • 网络通信2—UDP 模型程序编写步骤(参照 Ubuntu 16.04 版本)

    UDP 模型程序编写步骤 一 UDP基础模型 服务器流程 step 1 xff1a 创建 socket 套接字接口并判断 sockfd 61 socket AF INET SOCK DGRAM 0 if sockfd 61 61 1 per
  • switch 中 break 和 continue 的区别

    1 break 用来退出 switch xff0c continue 本身是不能用在 switch 里的 xff0c 他必须结合循环来用 xff0c 表示跳过本次循环 2 switch 的 case 语句最后如果没有加 break cont
  • 立即数

    一 概念 xff1a 通常把在 立即寻址方式 指令中给出的数称为立即数 二 判断步骤 xff1a 把数据转换成二进制 xff0c 从低到高写成 4 个一组 xff0c 最高位不够一组的补 0 xff1b 数 1 的个数 xff0c 如果大于
  • 位、字节、char、int(32位系统) 之间的关系

    一 概念 xff1a 位 xff08 bit xff09 xff1a 计算机中最小的数据单位 每一位的状态只能是0或1 字节 xff08 byte xff09 xff1a 存储空间的基本计量单位 xff0c 8 个二进制位构成1个字节 1
  • C语言中的那些宏

    DATE 进行预处理的日期 xff08 Mmm dd yyyy 形式的字符串文字 xff09 FILE 代表当前源代码文件名的字符串文字 LINE 代表当前源代码中的行号的整数常量 TIME 源文件编译时间 xff0c 格式微 hh xff
  • 任务栈简单入门

    最近又把两本进阶书看了一遍 xff0c 但总感觉好记性不如烂笔头 xff0c 所以还是决定通过博客记录一下 xff0c 我们将分两篇来全面深入地记录Activity 启动模式与任务栈的内容 android任务栈简单了解 1 android任

随机推荐

  • VS2010里函数枚举

    一 cout函数 说明 xff1a 调用该函数必须申明头文件 include lt iostream gt 同时声明后面必须使用 using namespace std 正确书写为 xff1a include lt iostream gt
  • I_O—标准 I_O 实验

    一 测试标准 I O 一次可以同时打开多少个文件 1 实验思路 xff1a 利用循环同时打开文件 xff0c 直到不能打开 2 代码如下 xff1a 二 fgetc 和 fputc 实现拷贝文件并输出文件行数 1 实验思路 xff1a 打开
  • Source Insight 配色方案

    Source Insight 对于程序员来说应该不陌生 xff0c 当然一个个性化的编程界面也会让自己赏析悦目 xff0c 下面就将个人的界面设置分享一下 xff1a 一 背景色设置 1 选择 Options Preferences 2 选
  • Linux 网络——交换机不能用两根网线相连

    同一个局域网所有的交换机之间可以用网线串联起来 xff0c 但绝对不能使任意 gt 61 2个交换机形成环路 xff0c 否则局域网内将形成广播风暴 xff0c 所用局域网内的用户都将不能上网 例如局域网内的交换机可以使用如下相连 xff1
  • GDB 知识点——基础操作

    Linux C 中的 GDB 调试使用 xff1a 1 GDB 的主要功能 xff1a 1 启动被调试程序 2 让被调试的程序在指定的位置停住 3 当程序被停住时 xff0c 可以检查程序状态 xff08 如变量的值 xff09 2 检查
  • 员工管理系统(C 语言)——项目说明

    项目名称 xff1a 员工管理系统 项目目的 xff1a 1 实现简单的公司对员工信息的管理 2 通过项目锻炼实现逻辑转换为代码的能力 3 利用函数封装实现项目过程中的逻辑过程以及需求功能的实现 4 学会数据库的操作以及网络通信 5 强化代
  • 员工管理系统(C 语言)——客户端解析

    源码下载地址 xff1a https download csdn net download wenfei11471 10477504 客户端功能 xff1a 1 运行时先测试是否能连通服务器 xff08 不畅通如下图所示 xff09 xff
  • 员工管理系统(C 语言)——服务器解析

    源码下载地址 xff1a https download csdn net download wenfei11471 10477504 服务器功能 xff1a 1 运行时主界面 xff08 服务器启动后 xff0c 只有管理员下线 xff0c
  • 排序——选择排序、冒泡排序和快速排序比较

    一 选择排序思路 xff1a 1 以 int 类型为例 2 拿第一个数与后面数相比较 xff0c 如果比后面的数大则交换 3 拿第二个数与后面的数比较 xff0c 如果比后面的数大则交换 4 直到比较到倒数第二个数 xff0c 最后一个数不
  • C 语言中 const 与指针的结合使用

    请区分一下几种指针的区别 1 const int p 2 int const p 3 int const p 4 const int const p 5 const int const p 解析 xff1a 1 const int p 中
  • Ubuntu16.04上安装百度网盘后打不开

    现在百度网盘推出了Linux版本 xff0c 也有Ubuntu下安装的deb文件 xff0c 但是我在Ubuntu上安装后却打不开 xff0c 报错 baidunetdisk crashed with SIGABRT in gnu cxx
  • C/C++的“文件包含”处理时头文件被重复包含的问题探究及解决方法(用最简单的例子进行说明)

    这篇博文是博文https blog csdn net wenhao ir article details 125668051的配套博文 头文件被重复包含是下面这样的现象 xff1a A文件里包含了C文件 xff0c B文件里也包含了C文件
  • BIN,BCD,ASCII码分别对应的Hex(16进制)数

    BIN BCD ASCII码分别对应的Hex xff08 16进制 xff09 数 以十进制的 56 为例 BIN 码 对应二进制数为 0011 1000对应Hex数据为 0x38BIN码就是二进制数 xff1b 压缩BCD 码 对应二进制
  • .LDS 文件详解

    最近在研究uboot xff0c 红色部分为我加上的注解 转载地址 xff1a http blog chinaunix net space php uid 61 23373524 amp do 61 blog amp cuid 61 232
  • 13 select的优化一

    1 上个例子中 xff0c select通过for循环轮询client套接字 xff0c 轮询的范围比较大 xff0c 有优化的地方 2 优化代码 xff1a 通过数组存储client的套接字 xff0c 达到少轮询的效果 xff0c 可以
  • 二.手写迷你版Tomcat-minicat2.0

    minicat 1 0我们实现了返回固定的字符串 34 Hello minicat 34 minicat 2 0需求 xff1a 封装Request和Response对象 xff0c 返回html静态资源文件 封装Request对象 想要封
  • 三.手写迷你版Tomcat-minicat3.0

    minicat 1 0我们实现了返回固定的字符串 34 Hello minicat 34 minicat 2 0封装Request和Response对象 xff0c 返回html静态资源文件 minicat 3 0需求 xff1a 请求se
  • python爬取全国五级行政区

    以前爬过国家统计局的四级行政区 xff08 http www stats gov cn tjsj tjbz tjyqhdmhcxhfdm 2017 xff09 xff0c 但是对于五级数据效果不是很好 偶然间发现这个网站 xff1a htt
  • ElasticSearch使用elasticsearchTemplate聚合查询

    这两天正好做个需求 xff0c 需要用到聚合查询 前几篇文章只是简单的提到过 xff0c 并没有真正的运用到实际产出中 xff0c 本篇结合实际代码 xff0c 专项学习ES的聚合查询 1 业务背景 有一张地址索引表 xff1a hisAd
  • Java字节码

    Java最黑科技的玩法就是字节码编程 xff0c 也就是动态修改或是动态生成 Java 字节码 使用字节码可以玩出很多高级的玩法 xff0c 最高级的还是在 Java 程序运行时进行字节码修改和代码注入 听起来是不是一些很黑客 xff0c