0%

一、人们如何做出决策

1.1 人们面临权衡取舍

选择一样东西就意味着你要放弃另外一样东西。认识到生活中的权衡是重要的,因为人们只有了解他们可以得到的选择,才能作出良好的决策。

1.2 某种东西的成本是为了得到它而放弃的东西

一种东西的机会成本是为了得到这种东西所放弃的东西

1.3 理性人考虑边际量

生活中的许多决策涉及到对现有行动计划进行微小的增量调整。 经济学家把这些调整称为边际变动。
个人和企业通过考虑边际量将会作出更好的决策。只有一种行动的边际收益大于边际成本,一个理性决策者才 会采取这项行动。

1.4 人们会对激励作出反应
  • 由于理性人通过比较成本与收益🉐做出决策,所以他们会对激励做出反应。
  • 在分析任何一种政策时,不仅应该考虑直接影响,而且还应该考 虑激励发生作用的间接影响。
  • 如果政策改变了激励,它就将使人们改 变自己的行为。

二、人们如何相互影响

2.1 贸易能使每个人的状况变得更好

贸易使各国可以专 门从事自己最擅长活动,并享有很多的各种各样物品与劳务

2.2 市场通常是组织经济活动的一种好方法
  • 在市场经济中,中央计划者的决策被千百万企业和家庭的决策所取代。
  • 价格和利己引导人们决策
  • 价格就是看不见的手用来指引经济活动的工具
  • 当政府阻止价格根据供求状况自发调整时,他就限制了看不见的手🤚对组成经济的千百万家庭👪和企业的决策进行协调的能力
2.3 政府有时可以改善市场结果
  • 只有在政府实施规则并维护对市场经济至关重要的制度时,看不见的手才能施展其魔力。
  • 看不见的手🤚是强有力的,但并不是无所不能的。政府干预经济的原因有两类:促进效率和促进平等。

三、整体经济如何运行

3.1 一国的生活水平取决于它生产物品与服务的能力

生产率:每单位劳动投入所生产的物品与服务数量。

3.2 当政府发行了过多货币时,物价上升
3.3 社会面临通货膨胀与失业之间的短期权衡取舍
  • 货币的增加刺激社会的整体支出水平,从而增加对物品与服务的需求
  • 需求的增加随着时间的推移,会引起企业提高物价,同时它也鼓励企业雇佣更多的工人👷,并生产更多的物品与服务
  • 雇佣更多的工人👷意味着更少的失业。

一、可重定位文件

1
2
3
4
5
6
7
8
9
//main.c                    //x.c

extern void foo(void); | #include <stdio.h>
|
int main(void) | void foo()
{ | {
foo(); | printf("foo\n");
return 0; | }
} |
1
2
3
4
5
6
7
8
9
> objdump -d main.o
00000000 <main>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 e4 f0 and $0xfffffff0,%esp
6: e8 fc ff ff ff call 7 <main+0x7>
b: b8 00 00 00 00 mov $0x0,%eax
10: c9 leave
11: c3 ret

在编译和汇编阶段,[main.c -> main.o] 汇编器无法确定外部定义的函数和全局变量的地址,所以它只能使用一个假地址占位,并产生一条额外的记录,让后面的链接器使用这条记录帮它完成地址修正。这条记录对于代码段来说放在[.rel.text] ,对于数据段来说放在[.rel.data],它们都是重定位文件的一个section。

对于每一条记录都对应于如下的一个数据结构:

1
2
3
4
5
typedef struct {
Elf32_Addr r_offset;
uint32_t r_info;
int32_t r_addend;
} Elf32_Rela;

二、静态链接

1、多个目标文件的合并:

2、对代码段,数据段以及各符号进行地址分配
3、根据 [relocation entries] 重新计算代码和数据段中的假地址。

三、动态链接

1、静态链接的缺点
  • 静态链接将使一些公用代码如libc库产生冗余,浪费内存和磁盘空间
  • 如果模块化开发,一个模块更新就得重新链接
2、动态链接的概念

相较于静态链接在编译期进行链接操作,将链接过程推迟到运行时进行的过程叫动态链接。

3、动态链接的实现

3.1 地址无关代码
由于在运行时,代码段是共享的,只能读不能写,所以需要将指令中那些需要修改的部分分离出来,跟数据部分放在一起,这样指令部分就可以保持不变,而数据部分可以在每一个进程中拥有一个副本。

3.2 全局偏移表(Global Offset Table)
当链接过程发生在运行期时,外部的符号调用只有在运行时装载模块后才能确定模块被装载的地址,以及模块内符号的确切地址。所以ELF提供了一个全局偏移表(GOT)来记录这些外部模块的符号引用。当模块被装载时,会更新此表的内容。

四、参考文献

1.Linking
2.understanding-relocation-elf
3.ELF Binaries and Relocation Entries
4.static-linking-dynamic-linking
5.ELF函数重定位问题

英文名称 中文名称 计算方式 理解
PE = Price-to-Earning Ratio 市盈率 每股股价/每股盈余 = 市值/净利润 创造财富的能力、回收成本的时间
PS = Price-to-Sales Ratio 市销率 每股股价/每股营收 = 市值/营收 获得公司1元的销售收入需要投入多少钱
PCF =Price-to-Cash-Flow Ratio 市现率 每股股价/每股现金流 = 市值/12月现金流
PB = Price-to-Book Ratio 市净率 每股股价/每股净资产 = 市值/净资产 净资产的溢价程度

一、市盈率

1.1 PE - 静态市盈率

① 市盈率 = 当日收盘价 / 上一年度每股税后利润

② 市盈率 = 当前总市值 / 上年度净利润

理解:

  • 公司需要累计多少年的盈利才能达到目前的市价水平。
  • 值越低说明投资回收期短,风险越小,投资价值越高。
  • 值越大说明翻本期长,风险大。

缺点:

  • 取的是上一年度的净利润,是一个过去的值,有点滞后。

例子:
你花了240w买了一套二手房,打算进行出租赚点外快,已知去年平均月租2w,一年收益大概24w。以去年这些数据为参考,你预计十年后才能赚回成本240w,所以市盈率 = 10。

1.2 动态市盈率
为了弥补静态市盈率的滞后性,增加动态市盈率作为参考指标。

市盈率 = 当前总市值 / X

根据当前的时间节点不同计算X的值:
X = 当年最近一个季度的净利润 * 4
X = 最近半年净利润 * 2
X = 最近三季度净利润 * 1.5

1.3 静态市盈率 vs 动态市盈率

  • 静态市盈率反映的是过去的数据,动态市盈率反映的是未来的预估
  • 动态市盈率 > 静态市盈率,说明最近(一个季度、半年、三个季度)公司的利润下降了。

1.4 TTM-Trailing Twelve Months

  • 最近十二个月市盈率,也叫滚动市盈率。
  • 它也是一个对过去情况的分析说明。

二、每股净值产

每股净值产 = (总资产 - 总负债) / 总股数

三、市净率

3.1 PB-市净率

市净率 = 每股市价 / 每股净值产
每股净资产 = 股东权益 / 总股本

市净率越低那么它的投资价值就越高,这也就意味着它的风险越低。

一、概述

代码是解决问题的工具。当通过编码方式解决一个问题时,通常有如下步骤:

  • 定义问题
  • 设计解决方案
  • 编码实现方案
  • 测试程序

编码实现通常是我们利用计算机高级语言书写的,符合一定逻辑的程序代码,这种含逻辑的代码计算机是无法理解的,它能理解的只是一条条由0和1组成的指令即机器语言。所以这就涉及从高级语言到机器语言的翻译和转换过程,处理这个过程的程序叫编译器

编译器这个程序,很庞大很复杂,为了让它简洁,好控制,我们把它拆成四个部分:

  • 预处理器
  • 编译器
  • 汇编器
  • 链接器

每一个阶段基本上都是在为下一个阶段做准备,它的过程如下图所示:

预处理器(Preprocessor)处理代码的过程叫预处理阶段,它所做的工作包括:

  • #define宏定义展开
  • 处理条件编译指令
  • 处理#include指令
  • 删除注释
  • 添加行号
  • 保留#pragma指令

编译器(Compiler)处理代码的过程叫编译,它主要是将上一步的产物转换成汇编代码,它的工作内容包括:

  • 词法分析
  • 语法分析
  • 语义分析
  • 优化

汇编器(Assembler)处理代码的过程叫汇编过程,它主要将汇编代码转换成二进制的机器码

  • 汇编码到机器码的翻译

链接器(Linker)处理代码的过程叫链接过程,多个文件合并成一个文件

  • 空间与地址分配-相同部分合并
  • 符号解析和重定位-合并后位置(偏移量)调整

综上可知,目标文件是程序未链接前的一个中间文件。目标文件内容的存储方式符合ELF文件标准,所以他是一种特殊的ELF文件。

二、文件结构解析

目标文件其实是ELF文件的一种,常见的ELF文件还有.so和.oat文件等。ELF文件存在两种观察角度,分别是编译角度和运行角度。编译角度是指,在代码编译阶段的存储格式。运行角度是指,文件被加载进内存时的存储格式。
两个角度看到的结构略有差异。如图:

从图中可以得到这样一些信息:
1、Program Header Table对于编译视图是可选的,因为它只在程序被加载进内存时使用到。Section Header Table对于执行视图是可选的。
2、编译视图是以section为组织单位,执行视图是以segment为组织单位(多个section会被映射到同一个segment)。

下面介绍一些重要的结构。

ELF Header-文件的总体结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#define EI_NIDENT 16
typedef struct {
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type; /* 此elf文件的类型见下表 */
Elf32_Half e_machine; /* CPU平台架构 */
Elf32_Word e_version; /* 此文件的版本 */
Elf32_Addr e_entry; /* 加载完该程序后的执行入口 */
Elf32_Off e_phoff; /* program header table在文件中的偏移量 */
Elf32_Off e_shoff; /* section header table在此文件中的偏移量 */
Elf32_Word e_flags; /* processor-specific flags associated with the file */
Elf32_Half e_ehsize; /* the ELF header's size in bytes. */
Elf32_Half e_phentsize; /* program-header-table数组中一个元素的大小 */
Elf32_Half e_phnum; /* program-header-table数组元素的个数 */
Elf32_Half e_shentsize; /* section header table数组中一个元素的大小 */
Elf32_Half e_shnum; /* section header table包含的元素个数 */
Elf32_Half e_shstrndx; /* the section header table index of the entry associated with the section name string table. */
} Elf32_Ehdr;
文件类型 类型描述
ET_NONE 未知类型。这个标记表明文件类型不确定,或者还未定义。
ET_REL 重定位文件。 ELF 类型标记为 relocatable 意味着该文件被标记为了一段可重定位的代码,有时也称为目标文件。可重定位 目标文件通常是还未被链接到可执行程序的一段位置独立的代码 (position independent code)。 在编译完代码之后通常可以看到一 个.o 格式的文件, 这种文件包含了创建可执行文件所需要的代码 和数据。
ET_EXEC 可执行文件。ELF 类型为 executable,表明这个文件被标 记为可执行文件。这种类型的文件也称为程序,是一个进程开始执 行的入口。
ET_DYN 共享目标文件。ELF 类型为 dynamic,意味着该文件被标记 为了一个动态的可链接的目标文件,也称为共享库。这类共享库会在 程序运行时被装载并链接到程序的进程镜像中。
ET_CORE 核心文件。在程序崩溃或者进程传递了一个 SIGSEGV 信 号(分段违规)时,会在核心文件中记录整个进程的镜像信息。可以 使用 GDB 读取这类文件来辅助调试并查找程序崩溃的原因。

file /bin/bash //executable
file /xxx/xx.so //shared object

Program Header Table

程序装载时,根据此结构的信息对文件进行分段(segment)。描述了磁盘上可执行文件的内存布局以及如何映射到内存中。

1
2
3
4
5
6
7
8
9
10
typedef struct {
uint32_t p_type; /* 此元素描述的是哪种segment,以及如何解析 */
Elf32_Off p_offset; /* segment首字节在文件中的偏移值 */
Elf32_Addr p_vaddr; /* 应该加载到内存中的哪个虚拟地址中 */
Elf32_Addr p_paddr; /* 相关的物理地址,BSD中为0 */
uint32_t p_filesz; /* 文件的字节数 */
uint32_t p_memsz; /* 加载到内存中的字节数 */
uint32_t p_flags; /* segment类型标志位 */
uint32_t p_align; /* 内存对齐 */
} Elf32_Phdr;
p_flags 描述
PF_X An executable segment.
PF_W A writable segment.
PF_R A readable segment.
Section Header Table

用于定位文件中所有的section,主要用于链接和调试,没有Section Header Table程序仍然可以正常运行,因为它没有对内存布局进行描述,它是一个元素为Elf32_Shdr的数组结构。

1
2
3
4
5
6
7
8
9
10
11
12
13
typedef struct
{
Elf32_Word sh_name; /* Section name (string tbl index) */
Elf32_Word sh_type; /* Section type */
Elf32_Word sh_flags; /* Section flags */
Elf32_Addr sh_addr; /* Section virtual addr at execution */
Elf32_Off sh_offset; /* Section file offset */
Elf32_Word sh_size; /* Section size in bytes */
Elf32_Word sh_link; /* Link to another section */
Elf32_Word sh_info; /* Additional section information */
Elf32_Word sh_addralign; /* Section alignment */
Elf32_Word sh_entsize; /* Entry size if section holds table */
} Elf32_Shdr;
Section type 描述
SHT_NULL This value marks the section header as inactive. It does not have an associated section. Other members of the section header have undefined values.
SHT_PROGBITS This section holds information defined by the program, whose format and meaning are determined solely by the program.
SHT_SYMTAB This section holds a symbol table. Typically, SHT_SYMTAB provides symbols for link editing, though it may also be used for dynamic linking. As a complete symbol table, it may contain many symbols unnecessary for dynamic linking. An object file can also contain a SHT_DYNSYM section.
SHT_STRTAB This section holds a string table. An object file may have multiple string table sections.
SHT_RELA This section holds relocation entries with explicit addends, such as type Elf32_Rela for the 32-bit class of object files. An object may have multiple relocation sections.
SHT_HASH This section holds a symbol hash table. An object participating in dynamic linking must contain a symbol hash table. An object file may have only one hash table.
SHT_DYNAMIC This section holds information for dynamic linking. An object file may have only one dynamic section.
SHT_NOTE This section holds notes (ElfN_Nhdr).
SHT_NOBITS A section of this type occupies no space in the file but otherwise resembles SHT_PROGBITS. Although this section contains no bytes, the sh_offset member contains the conceptual file offset.
SHT_REL This section holds relocation offsets without explicit addends, such as type Elf32_Rel for the 32-bit class of object files. An object file may have multiple relocation sections.
SHT_SHLIB This section is reserved but has unspecified semantics.
SHT_DYNSYM This section holds a minimal set of dynamic linking symbols. An object file can also contain a SHT_SYMTAB section.
SHT_LOPROC, SHT_HIPROC Values in the inclusive range [SHT_LOPROC, SHT_HIPROC] are reserved for processor-specific semantics.
SHT_LOUSER This value specifies the lower bound of the range of indices reserved for application programs.
SHT_HIUSER This value specifies the upper bound of the range of indices reserved for application programs. Section types between SHT_LOUSER and SHT_HIUSER may be used by the application, without conflicting with current or future system-defined section types.
字符串表和符号表(String and symbol tables)

存放scetion的名字,以及符号信息。其他结构通过index访问此结构中的字符串信息。符号表保存了用于定位符号引用的信息。它是以下结构的数组:

1
2
3
4
5
6
7
8
typedef struct {
uint32_t st_name;
Elf32_Addr st_value;
uint32_t st_size;
unsigned char st_info;
unsigned char st_other;
uint16_t st_shndx;
} Elf32_Sym;
Relocation entries (Rel & Rela)

重定位是连接符号引用(函数的名字)和符号定义(函数的定义、函数的实现)的过程。重定位文件必须包含如何修改section内容的信息,来让执行文件或共享目标文件正确的调用外部函数。

1
2
3
4
5
6
7
8
9
10
typedef struct {
Elf32_Addr r_offset;
Elf32_Word r_info;
} Elf32_Rel;

typedef struct {
Elf32_Addr r_offset;
Elf32_Word r_info;
Elf32_Sword r_addend;
} Elf32_Rela;

r_offset:
对于重定位文件来说,此值表示从section的开始到被修改值在section中的偏移量。
对于执行文件和共享库文件来说,此值表示需要被重定位的虚拟地址。

r_info:
符号表的index和重定位的类型。

r_addend:
用于计算重定位字段的值。

Dynamic tags(Dyn)

.dynamic这个section存储一些包含动态链接信息的结构

1
2
3
4
5
6
7
8
9
typedef struct {
Elf32_Sword d_tag;
union {
Elf32_Word d_val;
Elf32_Addr d_ptr;
} d_un;
} Elf32_Dyn;

extern Elf64_Dyn _DYNAMIC[];

一些图示

三、参考链接

Linux manual page
The structure of an ARM ELF image
Compiling, Linking and Building

一、Class文件结构概览

1.1 概述
  • 每一个class文件包含一个类或者接口的定义
  • 以大端方式存储
  • u1、u2、u4分别表示1、2、4个字节
1.2 数据结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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];
}
1.3 图形化表示
1.4 示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface Car {
void drive();
}

public class BMWCar implements Car{

private String name;

public BMWCar() {
name = "宝马";
}

@Override
public void drive() {
System.out.println("BMW car drive." + name);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
Last modified 2017-11-10; size 644 bytes
MD5 checksum ac6d7477d45479490e4ea3f660b1dcdd
Compiled from "BMWCar.java"
public class BMWCar implements Car
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #12.#23 // java/lang/Object."<init>":()V
#2 = String #24 // 宝马
#3 = Fieldref #11.#25 // BMWCar.name:Ljava/lang/String;
#4 = Fieldref #26.#27 // java/lang/System.out:Ljava/io/PrintStream;
#5 = Class #28 // java/lang/StringBuilder
#6 = Methodref #5.#23 // java/lang/StringBuilder."<init>":()V
#7 = String #29 // BMW car drive.
#8 = Methodref #5.#30 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
#9 = Methodref #5.#31 // java/lang/StringBuilder.toString:()Ljava/lang/String;
#10 = Methodref #32.#33 // java/io/PrintStream.println:(Ljava/lang/String;)V
#11 = Class #34 // BMWCar
#12 = Class #35 // java/lang/Object
#13 = Class #36 // Car
#14 = Utf8 name
#15 = Utf8 Ljava/lang/String;
#16 = Utf8 <init>
#17 = Utf8 ()V
#18 = Utf8 Code
#19 = Utf8 LineNumberTable
#20 = Utf8 drive
#21 = Utf8 SourceFile
#22 = Utf8 BMWCar.java
#23 = NameAndType #16:#17 // "<init>":()V
#24 = Utf8 宝马
#25 = NameAndType #14:#15 // name:Ljava/lang/String;
#26 = Class #37 // java/lang/System
#27 = NameAndType #38:#39 // out:Ljava/io/PrintStream;
#28 = Utf8 java/lang/StringBuilder
#29 = Utf8 BMW car drive.
#30 = NameAndType #40:#41 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
#31 = NameAndType #42:#43 // toString:()Ljava/lang/String;
#32 = Class #44 // java/io/PrintStream
#33 = NameAndType #45:#46 // println:(Ljava/lang/String;)V
#34 = Utf8 BMWCar
#35 = Utf8 java/lang/Object
#36 = Utf8 Car
#37 = Utf8 java/lang/System
#38 = Utf8 out
#39 = Utf8 Ljava/io/PrintStream;
#40 = Utf8 append
#41 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder;
#42 = Utf8 toString
#43 = Utf8 ()Ljava/lang/String;
#44 = Utf8 java/io/PrintStream
#45 = Utf8 println
#46 = Utf8 (Ljava/lang/String;)V
{
public BMWCar();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: ldc #2 // String 宝马
7: putfield #3 // Field name:Ljava/lang/String;
10: return
LineNumberTable:
line 6: 0
line 7: 4
line 8: 10

public void drive();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=3, locals=1, args_size=1
0: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
3: new #5 // class java/lang/StringBuilder
6: dup
7: invokespecial #6 // Method java/lang/StringBuilder."<init>":()V
10: ldc #7 // String BMW car drive.
12: invokevirtual #8 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
15: aload_0
16: getfield #3 // Field name:Ljava/lang/String;
19: invokevirtual #8 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: invokevirtual #9 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
25: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
28: return
LineNumberTable:
line 12: 0
line 13: 28
}
SourceFile: "BMWCar.java"

二、常量池的结构

常量池是一个cp_info的数组:通过tag定位到具体的数据结构,再通过数据结构的表示,判断下面几个字节怎么解析。

1
2
3
4
cp_info {
u1 tag; //cp-info的类型
u1 info[];//类型对应的数组
}
tag info 数据结构 描述
1 CONSTANT_Utf8_info CONSTANT_NameAndType_info {
 u1 tag;
 u2 name_index;
 u2 descriptor_index;
}
UTF-8编码的字符串
3 CONSTANT_Integer_info CONSTANT_Integer_info {
 u1 tag;
 u4 bytes;
}
整形字面量,boolean、byte、char、short等类型都用int存放
4 CONSTANT_Float_info CONSTANT_Float_info {
 u1 tag;
 u4 bytes;
}
浮点型字面量
5 CONSTANT_Long_info CONSTANT_Long_info {
 u1 tag;
 u4 high_bytes;
 u4 low_bytes;
}
浮点型字面量
6 CONSTANT_Double_info CONSTANT_Long_info {
 u1 tag;
 u4 high_bytes;
 u4 low_bytes;
}
双精度浮点型字面量
7 CONSTANT_Class_info CONSTANT_Class_info {
 u1 tag;
 u2 name_index;
}
类或接口的符号引用
8 CONSTANT_String_info CONSTANT_String_info {
 u1 tag;
 u2 string_index;
}
字符串类型字面量
9 CONSTANT_Fieldref_info CONSTANT_Fieldref_info {
 u1 tag;
 u2 class_index;//索引值
 u2 name_and_type_index;
}
字段的符号引用
10 CONSTANT_Methodref_info CONSTANT_Methodref_info {
 u1 tag;
 u2 class_index;;//索引值
 u2 name_and_type_index;
}
类中方法的符号引用
11 CONSTANT_InterfaceMethodref CONSTANT_InterfaceMethodref_info {
 u1 tag;
 u2 class_index;;//索引值
 u2 name_and_type_index;
}
接口中方法的符号引用
12 CONSTANT_NameAndType_info CONSTANT_NameAndType_info {
 u1 tag;
  u2 name_index;
  u2 descriptor_index;
}
接口中方法的符号引用

三、字段的结构

每一个字段用一个 field_info的结构体表示

1
2
3
4
5
6
7
field_info {
u2 access_flags;
u2 name_index;//指向常量池的index,表示字段名
u2 descriptor_index;//指向常量池的inde,字段的描述符
u2 attributes_count;
attribute_info attributes[attributes_count];
}

四、方法的结构

1
2
3
4
5
6
7
method_info {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];//Code字节码信息
}

五、属性的结构

1
2
3
4
5
attribute_info {
u2 attribute_name_index;
u4 attribute_length;
u1 info[attribute_length];
}

六、参考链接

Chapter 4. The class File Format

Java Class文件结构解析

一、What、Why(是什么、为什么)

1.1 什么是分区存储
了解传统的共享存储 (Shared Storage):

  • 每个app有独立的存储空间Android/data/pkg其他应用不可见(Context.getExternalFileDir)
  • 访问外部空间需要额外权限READ/WRITE_EXTERNAL_STORAGE、获取存储权限的应用可以访问整个外部存储空间
  • 应用卸载时,保存在外部存储空间文件不会被删除。
阅读全文 »

Leetode-2 两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。请你将两个数相加,并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

阅读全文 »