class文件格式中的属性信息

附加属性(Attributes)被用于ClassFile, field_info, method_info,Code_attribute结构中。

数据结构:

attribute_info {
    u2 attribute_name_index;        //unsigned 16-bit ->  CONSTANT_Utf8_info
    u4 attribute_length;            //bytes
    u1 info[attribute_length];
}

aadfadfadfadfadf

属性 | class版本 | Java SE版本 | 位置 | 类型 | 作用 | 说明 ---|---|---|---|--|---|---- ConstantValue | 45.3 | 1.0.2 | field_info | F | 用于常量初始化赋值,如没有常量字段则忽略 | 必有 Code | 45.3 | 1.0.2 | method_info | V | JVM指令,包括构造器 | 必有 StackMapTable | 50.0 | 6 | Code | V | 在运行时,提供类型检查(可直接通过table,而不需要类型推测) | 必有 Exceptions | 45.3 | 1.0.2 | method_info | V | 方法可能抛出的异常(checked) | 必有 InnerClasses | 45.3 | 1.0.2 | ClassFile | V | 内部类 | 可选,JavaSE EnclosingMethod | 49.0 | 5.0 | ClassFile | F | 仅当局部类、匿名内部类 | 可选,JavaSE Synthetic | 45.3 | 1.1 | ClassFile, field_info, method_info | F | 非源码/编译器产生(不包括实例初始化方法;类/接口初始化方法;Enum.values();Enum.valueOf())|可选,JavaSE Signature | 49.0 | 5.0 | ClassFile, field_info, method_info | F | 签名;主要用于反射/DEBUG/{B C D F I J S Z;V;...} | 可选,JavaSE SourceFile | 45.3 | 1.0.2 | ClassFile | F | 最多一个 | 可选,JavaSE SourceDebugExtension | 49.0 | 5.0 | ClassFile | V | 可选,最多一个;扩展的DEBUG信息 | 可选,元数据,JavaSE LineNumberTable | 45.3 | 1.0.2 | Code | V | code对应的源码行数 | 可选,JavaSE LocalVariableTable | 45.3 | 1.0.2 | Code | V | 在运行期方便的跟踪局部变量/参数(槽位Slot分布) | 可选,JavaSE LocalVariableTypeTable | 49.0 | 5.0 | Code | V | 在运行期方便的跟踪局部变量/参数 | 可选,JavaSE Deprecated | 45.3 | 1.1 | ClassFile, field_info, method_info | F | 标记性 | 可选,元数据,JavaSE RuntimeVisibleAnnotations | 49.0 | 5.0 | ClassFile,field_info,method_info | V | 声明注解运行时可见 | 可选,元数据,JavaSE RuntimeInvisibleAnnotations | 49.0 | 5.0 | ClassFile,field_info,method_info | V | 声明注解运行时不可见 | 可选,元数据,JavaSE RuntimeVisibleParameterAnnotations | 49.0 | 5.0 | method_info | V | 运行时,参数的注解可见 | 可选,元数据,JavaSE RuntimeInvisibleParameterAnnotations | 49.0 | 5.0 | method_info | V | 运行时,参数的注解不可见 | 可选,元数据,JavaSE RuntimeVisibleTypeAnnotations | 52.0 | 8 | ClassFile,field_info,method_info, Code | V | 用于声明式/表达式的运行时可见注解 | 可选,元数据,JavaSE RuntimeInvisibleTypeAnnotations | 52.0 | 8 | ClassFile,field_info,method_info, Code | V | 用于声明式/表达式的运行时不可见注解 | 可选,元数据,JavaSE AnnotationDefault | 49.0 | 5.0 | method_info | V | 注解默认值(default关键字) | 可选,元数据,JavaSE BootstrapMethods | 51.0 | 7 | ClassFile | V | 记录动态方法信息(被invokedynamic指令调用);需要与CONSTANT_InvokeDynamic_info对应 | 必有 MethodParameters | 52.0 | 8 | method_info | V | 用于记录表达式形式的方法参数 | 可选,元数据,JavaSE Module | 53.0 | 9 | ClassFile | V | 用于标记JAVA 9的模块 | 可选,元数据,JavaSE ModulePackages | 53.0 | 9 | ClassFile | V | 包括所有exported或opened的Module属性 | 可选,元数据,JavaSE ModuleMainClass | 53.0 | 9 | ClassFile | F | 指明Module的主类 | 可选,元数据,JavaSE

  • ConstantValue
ConstantValue_attribute {
    u2 attribute_name_index;        //CONSTANT_Utf8_info
    u4 attribute_length;
    u2 constantvalue_index;         //constant_pool中的一个值
}

Constant value attribute types:

Field TypeEntry Type
longCONSTANT_Long
floatCONSTANT_Float
doubleCONSTANT_Double
int, short, char, byte, booleanCONSTANT_Integer
StringCONSTANT_String
  • Code
Code_attribute {
    u2 attribute_name_index;                        // CONSTANT_Utf8_info -> constant_pool -> "Code"
    u4 attribute_length;                            // excluding the initial six bytes
    u2 max_stack;                                   
    u2 max_locals;                                  // local variables/parameters/long or double is max_locals - 2
    u4 code_length;                                 // (0,65536)
    u1 code[code_length];                           // 读入内存后可按字节寻址(byte-addressable),
                                                    // 数组起始(第一个字节)位置按4字节对齐
                                                    //(tableswitch and lookupswitch 32-bit offsets will be 4-byte aligned)
    u2 exception_table_length;                      // number of entries in the exception_table table
    { 
        u2 start_pc;                                // ranges in the code array [start_pc, end_pc)
        u2 end_pc;                                  // ranges in the code array [start_pc, end_pc)
        u2 handler_pc;                              // 
        u2 catch_type;                              // CONSTANT_Class_info -> constant_pool
                                                    // zero, => finally
    } exception_table[exception_table_length];  
    u2 attributes_count;                            // 
    attribute_info attributes[attributes_count];    // optional
}
  • StackMapTable
    • 栈图,其方法的code属性中存储了局部变量和操作数的类型验证以及字节码的偏移量
    • 必须准确知道每个字节码指令对应的局部变量和操作数栈的类型
    • 因为Java7在编译的时期做了一些验证期间要做的事情,那就是类型检查,也就是栈图包含的内容
    • 代码跳转,分支,goto时,对变量和指令进行校验
    • 第一个隐式
StackMapTable_attribute {
    u2 attribute_name_index;                        // CONSTANT_Utf8_info -> constant_pool -> "StackMapTable"
    u4 attribute_length;                            // excluding the initial six bytes
    u2 number_of_entries;                           // the number of stack_map_frame entries in the entries table
    stack_map_frame entries[number_of_entries];     // stack map frame
}
union verification_type_info {
    Top_variable_info;
    Integer_variable_info;
    Float_variable_info;
    Long_variable_info;
    Double_variable_info;
    Null_variable_info;
    UninitializedThis_variable_info;
    Object_variable_info;
    Uninitialized_variable_info;
}
Top_variable_info {
    u1 tag = ITEM_Top; /* 0 */
}

Integer_variable_info {
    u1 tag = ITEM_Integer; /* 1 */
}

Float_variable_info {
    u1 tag = ITEM_Float; /* 2 */
}

Double_variable_info {
    u1 tag = ITEM_Double; /* 3 */
}

Long_variable_info {
    u1 tag = ITEM_Long; /* 4 */
}

Null_variable_info {
    u1 tag = ITEM_Null; /* 5 */
}

UninitializedThis_variable_info {
    u1 tag = ITEM_UninitializedThis; /* 6 */
}

Object_variable_info {
    u1 tag = ITEM_Object; /* 7 */
    u2 cpool_index;
}

Uninitialized_variable_info {
    u1 tag = ITEM_Uninitialized; /* 8 */
    u2 offset;
}

frame_type:

union stack_map_frame {
    same_frame;                                     // [0-63]
                                                    // 表示与前一个栈帧有着同样的局部变量,且前一个操作栈为空
                                                    // offset_delta = frame_type
    same_locals_1_stack_item_frame;                 // [64, 127] 
                                                    // 表示与前一个栈帧有着同样的局部变量,且前一个操作栈有一个实体
                                                    // offset_delta = frame_type - 64
    same_locals_1_stack_item_frame_extended;        // 247
                                                    // 表示与前一个栈帧有着同样的局部变量,且前一个操作栈有一个实体
                                                    // 与上一个不同的是,偏移量明确给出
    chop_frame;                                     // [248-250]
                                                    // 表示与前一个栈帧除了最后K个变量不同,其他局部变量不变,且操作栈为空
                                                    // K = 251 - frame_type
    same_frame_extended;                            // 251
                                                    // 表示与前一个栈帧有着同样的局部变量,且操作栈为空
    append_frame;                                   // [252-254]
                                                    // 表示与前一个栈帧除了K个变量不同,其他局部变量不变,且操作栈为空
                                                    // K = frame_type - 251
    full_frame;                                     // 255
                                                    //
}
same_frame {
    u1 frame_type = SAME; /* 0-63 */
}

same_locals_1_stack_item_frame {
    u1 frame_type = SAME_LOCALS_1_STACK_ITEM; /* 64-127 */
    verification_type_info stack[1];
}

same_locals_1_stack_item_frame_extended {
    u1 frame_type = SAME_LOCALS_1_STACK_ITEM_EXTENDED; /* 247 */
    u2 offset_delta;
    verification_type_info stack[1];
}

chop_frame {
    u1 frame_type = CHOP; /* 248-250 */
    u2 offset_delta;
}

same_frame_extended {
    u1 frame_type = SAME_FRAME_EXTENDED; /* 251 */
    u2 offset_delta;
}

append_frame {
    u1 frame_type = APPEND; /* 252-254 */
    u2 offset_delta;
    verification_type_info locals[frame_type - 251];        // locals[M+1] represents local variable N+1 / N+2(Long_variable_info or Double_variable_info)
}

full_frame {
    u1 frame_type = FULL_FRAME; /* 255 */
    u2 offset_delta;
    u2 number_of_locals;
    verification_type_info locals[number_of_locals];        // locals[M+1] represents local variable N+1 / N+2(Long_variable_info or Double_variable_info)
    u2 number_of_stack_items;
    verification_type_info stack[number_of_stack_items];    // stack[M+1] represents stack entry N+1 / N+2(Long_variable_info or Double_variable_info)
}
  • Exceptions
Exceptions_attribute {
    u2 attribute_name_index;                            // CONSTANT_Utf8_info -> constant_pool -> "Exceptions"
    u4 attribute_length;                                // excluding the initial six bytes 
    u2 number_of_exceptions;                            // the number of entries in the exception_index_table
    u2 exception_index_table[number_of_exceptions];     // CONSTANT_Class_info -> constant_pool
}
  • InnerClasses
InnerClasses_attribute {
    u2 attribute_name_index;                    // CONSTANT_Utf8_info -> constant_pool -> "InnerClasses"
    u4 attribute_length;                        // excluding the initial six bytes
    u2 number_of_classes;                       // the number of entries in the classes array
    { 
        u2 inner_class_info_index;              // CONSTANT_Class_info -> constant_pool
        u2 outer_class_info_index;              // zero => [anonymous class , local class ,top-level class or interface]
                                                // CONSTANT_Class_info - constant_pool
        u2 inner_name_index;                    // zero => anonymous class
                                                // anonymous class -> constant_pool
        u2 inner_class_access_flags;            // Table 4.7.6-A. Nested class access and property flags
    } classes[number_of_classes];               // 
}
Flag NameFlag NameInterpretation
ACC_PUBLIC0x0001public
ACC_PRIVATE0x0002private
ACC_PROTECTED0x0004protected
ACC_STATIC0x0008static
ACC_FINAL0x0010final
ACC_INTERFACE0x0200interface
ACC_ABSTRACT0x0400abstract
ACC_SYNTHETIC0x1000非源码提供
ACC_ANNOTATION0x2000注解类型
ACC_ENUM0x4000枚举类型
  • EnclosingMethod
EnclosingMethod_attribute {
    u2 attribute_name_index;        // CONSTANT_Utf8_info -> constant_pool -> "EnclosingMethod"
    u4 attribute_length;            // 4
    u2 class_index;                 // CONSTANT_Utf8_info -> constant_pool
    u2 method_index;                // zero => current class is not immediately enclosed by a method or constructor
                                    // CONSTANT_NameAndType_info -> constant_pool
}
  • Synthetic
Synthetic_attribute {
    u2 attribute_name_index;        // CONSTANT_Utf8_info -> constant_pool -> "Synthetic" 
    u4 attribute_length;            // must be zero
}
  • Signature
Signature_attribute {
    u2 attribute_name_index;        // CONSTANT_Utf8_info -> constant_pool -> "Signature" 
    u4 attribute_length;            // 2
    u2 signature_index;             // CONSTANT_Utf8_info -> constant_pool
}
MethodSignature:
[TypeParameters] ( {JavaTypeSignature} ) Result {ThrowsSignature}
  • SourceFile
SourceFile_attribute {
    u2 attribute_name_index;        // CONSTANT_Utf8_info -> constant_pool -> "SourceFile" 
    u4 attribute_length;            // 2
    u2 sourcefile_index;            // CONSTANT_Utf8_info -> constant_pool
}
  • SourceDebugExtension
SourceDebugExtension_attribute {
    u2 attribute_name_index;                // CONSTANT_Utf8_info -> constant_pool -> "SourceDebugExtension"
    u4 attribute_length;                    // excluding the initial six bytes
    u1 debug_extension[attribute_length];   // modified UTF-8 string
}
  • LineNumberTable
LineNumberTable_attribute {
    u2 attribute_name_index;                        // CONSTANT_Utf8_info -> constant_pool -> "LineNumberTable"
    u4 attribute_length;                            // excluding the initial six bytes
    u2 line_number_table_length;                    
    {
        u2 start_pc;                                // 
        u2 line_number;
    } line_number_table[line_number_table_length];
}
  • LocalVariableTable
    • 可以有多个,不要求顺序
LocalVariableTable_attribute {
    u2 attribute_name_index;                                // CONSTANT_Utf8_info -> constant_pool -> "LocalVariableTable"
    u4 attribute_length;                                    // excluding the initial six bytes
    u2 local_variable_table_length;                         // the number of entries in the local_variable_table array
    { 
        u2 start_pc;                                        // 局部变量的作用域:[start_pc, start_pc + length)
        u2 length;
        u2 name_index;                                      // CONSTANT_Utf8_info -> constant_pool
        u2 descriptor_index;                                // CONSTANT_Utf8_info -> constant_pool
        u2 index;                                           // 槽位,遇到long / double 顺延 + 1
    } local_variable_table[local_variable_table_length];
}
  • LocalVariableTypeTable
    • 可以有多个,不要求顺序
LocalVariableTypeTable_attribute {
    u2 attribute_name_index;                                                // CONSTANT_Utf8_info -> constant_pool -> "LocalVariableTypeTable"
    u4 attribute_length;                                                    // excluding the initial six bytes
    u2 local_variable_type_table_length;
    { 
        u2 start_pc;                                                        //
        u2 length;
        u2 name_index;
        u2 signature_index;                                                 // CONSTANT_Utf8_info -> constant_pool
        u2 index;
    } local_variable_type_table[local_variable_type_table_length];
}
  • Deprecated
Deprecated_attribute {
    u2 attribute_name_index;        // CONSTANT_Utf8_info -> constant_pool -> "Deprecated"
    u4 attribute_length;            // must be zero
}
  • RuntimeVisibleAnnotations
RuntimeVisibleAnnotations_attribute {   
    u2 attribute_name_index;                        // CONSTANT_Utf8_info -> constant_pool -> "RuntimeVisibleAnnotations"
    u4 attribute_length;                            // excluding the initial six bytes
    u2 num_annotations;                             // 
    annotation annotations[num_annotations];        // annotation结构
}

annotation结构:

annotation {
    u2 type_index;                                      // CONSTANT_Utf8_info -> constant_pool -> descriptor
    u2 num_element_value_pairs;
    { 
        u2 element_name_index;                          // CONSTANT_Utf8_info -> constant_pool
        element_value value;                            // element_value结构
    } element_value_pairs[num_element_value_pairs];
}

element_value结构:

element_value {
    u1 tag;                                         // single ASCII
                                                    // Table 4.7.16.1-A
    union {
        u2 const_value_index;                       // CONSTANT_Utf8_info -> constant_pool
        { 
            u2 type_name_index;                     // CONSTANT_Utf8_info -> constant_pool
            u2 const_name_index;
        } enum_const_value;
        u2 class_info_index;                        // CONSTANT_Utf8_info -> constant_pool -> descriptor
                                                    // BaseType character
                                                    // void : V
        annotation annotation_value;                // nested annotation
        { 
            u2 num_values;
            element_value values[num_values];
        } array_value;                              // element-value pair
    } value;
}

Table 4.7.16.1-A. Interpretation of tag values as types

tag ItemTypevalue ItemConstant Type
Bbyteconst_value_indexCONSTANT_Integer
Ccharconst_value_indexCONSTANT_Integer
Ddoubleconst_value_indexCONSTANT_Double
Ffloatconst_value_indexCONSTANT_Float
Iintconst_value_indexCONSTANT_Integer
Jlongconst_value_indexCONSTANT_Long
Sshortconst_value_indexCONSTANT_Integer
Zbooleanconst_value_indexCONSTANT_Integer
sStringconst_value_indexCONSTANT_Utf8
eEnumtypeenum_const_value
cClassclass_info_indexNot applicable
@Annotationtypeannotation_value
[Arraytypearray_value
  • RuntimeInvisibleAnnotations
    • 类似RuntimeVisibleAnnotations
RuntimeInvisibleAnnotations_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 num_annotations;
    annotation annotations[num_annotations];
}
  • RuntimeInvisibleParameterAnnotations
RuntimeInvisibleParameterAnnotations_attribute {
    u2 attribute_name_index;                        // CONSTANT_Utf8_info -> constant_pool -> "RuntimeInvisibleParameterAnnotations"
    u4 attribute_length;
    u1 num_parameters;
    { 
        u2 num_annotations;
        annotation annotations[num_annotations];
    } parameter_annotations[num_parameters];
}
  • RuntimeVisibleTypeAnnotations
RuntimeVisibleTypeAnnotations_attribute {
    u2 attribute_name_index;                        // CONSTANT_Utf8_info -> constant_pool -> "RuntimeVisibleTypeAnnotations"
    u4 attribute_length;
    u2 num_annotations;
    type_annotation annotations[num_annotations];   // type_annotation结构
}

type_annotation结构:

type_annotation {
    u1 target_type;                                         // Table 4.7.20-A 
                                                            // Table 4.7.20-B
                                                            // Table 4.7.20-C 
    union {
        type_parameter_target;
        supertype_target;
        type_parameter_bound_target;
        empty_target;
        formal_parameter_target;
        throws_target;
        localvar_target;
        catch_target;
        offset_target;
        type_argument_target;
    } target_info;                                          // target_info结构
    type_path target_path;                                  // type_path结构
    u2 type_index;
    u2 num_element_value_pairs;
    { 
        u2 element_name_index;
        element_value value;
    } element_value_pairs[num_element_value_pairs];
}

target_info结构:

type_parameter_target {
    u1 type_parameter_index;
}

supertype_target {
    u2 supertype_index;
}

type_parameter_bound_target {
    u1 type_parameter_index;
    u1 bound_index;
}

empty_target {
}

formal_parameter_target {
    u1 formal_parameter_index;
}

throws_target {
    u2 throws_type_index;
}

localvar_target {
    u2 table_length;
    {
        u2 start_pc;
        u2 length;
        u2 index;
    } table[table_length];
}

catch_target {
    u2 exception_table_index;
}

offset_target {
    u2 offset;
}

type_argument_target {
    u2 offset;
    u1 type_argument_index;
}

type_path结构:

type_path {
    u1 path_length;
    { 
        u1 type_path_kind;              // Table 4.7.20.2-A
        u1 type_argument_index;
    } path[path_length];
}
  • RuntimeInvisibleTypeAnnotations
RuntimeInvisibleTypeAnnotations_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 num_annotations;
    type_annotation annotations[num_annotations];
}
  • AnnotationDefault
AnnotationDefault_attribute {
    u2 attribute_name_index;        // CONSTANT_Utf8_info -> constant_pool -> "AnnotationDefault"
    u4 attribute_length;            // excluding the initial six bytes
    element_value default_value;
}
  • BootstrapMethods
BootstrapMethods_attribute {
    u2 attribute_name_index;                                // CONSTANT_Utf8_info -> constant_pool -> "BootstrapMethods" 
    u4 attribute_length;                                    // excluding the initial six bytes
    u2 num_bootstrap_methods;
    { 
        u2 bootstrap_method_ref;                            // CONSTANT_MethodHandle_info
        u2 num_bootstrap_arguments;
        u2 bootstrap_arguments[num_bootstrap_arguments];    // constant_pool index
    } bootstrap_methods[num_bootstrap_methods];             // 
}
  • MethodParameters
MethodParameters_attribute {
    u2 attribute_name_index;            // CONSTANT_Utf8_info -> constant_pool -> "MethodParameters" 
    u4 attribute_length;                // excluding the initial six bytes
    u1 parameters_count;
    { 
        u2 name_index;                  // CONSTANT_Utf8_info -> constant_pool
        u2 access_flags;                // 0x0010 (ACC_FINAL)
                                        // 0x1000 (ACC_SYNTHETIC)
                                        // 0x8000 (ACC_MANDATED)
    } parameters[parameters_count];
}
  • Module
Module_attribute {
    u2 attribute_name_index;                    // CONSTANT_Utf8_info -> constant_pool -> "Module" 
    u4 attribute_length;                        // excluding the initial six bytes
    u2 module_name_index;                       // CONSTANT_Module_info -> constant_pool
    u2 module_flags;                            // 0x0020 (ACC_OPEN)
                                                // 0x1000 (ACC_SYNTHETIC)
                                                // 0x8000 (ACC_MANDATED)
    u2 module_version_index;                    // CONSTANT_Utf8_info -> constant_pool
    u2 requires_count;
    { 
        u2 requires_index;                      // CONSTANT_Module_info -> constant_pool
        u2 requires_flags;                      // 0x0020 (ACC_TRANSITIVE)
                                                // 0x0040 (ACC_STATIC_PHASE)
                                                // 0x1000 (ACC_SYNTHETIC)
                                                // 0x8000 (ACC_MANDATED)
        u2 requires_version_index;              // CONSTANT_Utf8_info -> constant_pool
    } requires[requires_count];
    u2 exports_count;
    { 
        u2 exports_index;                       // CONSTANT_Package_info -> constant_pool
        u2 exports_flags;                       // 0x1000 (ACC_SYNTHETIC)
                                                // 0x8000 (ACC_MANDATED)
        u2 exports_to_count;
        u2 exports_to_index[exports_to_count];  // CONSTANT_Module_info -> constant_pool
    } exports[exports_count];
    u2 opens_count;
    { 
        u2 opens_index;                         // CONSTANT_Package_info -> constant_pool
        u2 opens_flags;                         // 0x1000 (ACC_SYNTHETIC)
                                                // 0x8000 (ACC_MANDATED)
        u2 opens_to_count;
        u2 opens_to_index[opens_to_count];      // CONSTANT_Module_info -> constant_pool
    } opens[opens_count];
    u2 uses_count;
    u2 uses_index[uses_count];                  // CONSTANT_Class_info -> constant_pool
    u2 provides_count;
    { 
        u2 provides_index;                              // CONSTANT_Class_info -> constant_pool
        u2 provides_with_count;
        u2 provides_with_index[provides_with_count];    // CONSTANT_Class_info -> constant_pool
    } provides[provides_count];
}
  • ModulePackages
ModulePackages_attribute {
    u2 attribute_name_index;            // CONSTANT_Utf8_info -> constant_pool -> "ModulePackages" 
    u4 attribute_length;                // excluding the initial six bytes
    u2 package_count;
    u2 package_index[package_count];    // CONSTANT_Package_info -> constant_pool
}
  • ModuleMainClass
ModuleMainClass_attribute {
    u2 attribute_name_index;        // CONSTANT_Utf8_info -> constant_pool -> "ModuleMainClass" 
    u4 attribute_length;            // excluding the initial six bytes
    u2 main_class_index;            // CONSTANT_Class_info -> constant_pool
}

转载于:https://my.oschina.net/roccn/blog/1552792

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值