黑马程序员技术交流社区
标题:
学习序列之三:Java Class文件结构分析
[打印本页]
作者:
荣凯旋
时间:
2012-1-28 13:02
标题:
学习序列之三:Java Class文件结构分析
Code 属性用于 method_info 结构中。
4. Exceptions : attribute_info 被替代为 :
Exceptions_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 number_of_exceptions;
u2 exception_index_table[number_of_exceptions];
}
5. InnerClasses : attribute_info 被替代为 :
InnerClasses_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 number_of_classes;
{ u2 inner_class_info_index;
u2 outer_class_info_index;
u2 inner_name_index;
u2 inner_class_access_flags;
} classes[number_of_classes];
}
6. Synthetic : attribute_info 被替代为 :
Synthetic_attribute {
u2 attribute_name_index; // 不用废话了吧 ?
u4 attribute_length; // 必须为 0
}
Synthetic 用在 field_info 、 method_info 中,
一个没有出现在源程序中的变量必须使用 Synthetic 标记。
7. LineNumberTable : attribute_info 被替代为 :
LineNumberTable_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 line_number_table_length;
{ u2 start_pc; // 代码数组中的开始处
u2 line_number; // 源文件中的行号 ( 对于每一非空行都有这么一项 )
} line_number_table[line_number_table_length];
}
LineNumberTable 用于 Code 属性中,通常用于调试。
8. LocalVariableTable : attribute_info 被替代为 :
LocalVariableTable_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 local_variable_table_length;
{ u2 start_pc;
u2 length; // 当解释到代码数组的 [start_pc,start_pc+length]
// 时变量必须被赋值 ??
u2 name_index;
u2 descriptor_index;
u2 index; // 到本地变量数组的一个索引
} local_variable_table[local_variable_table_length];
}
9. Deprecated : attribute_info 被替代为 :
Deprecated_attribute {
u2 attribute_name_index;
u4 attribute_length; // 必须为 0
}
当然也可以定义自己的属性,但要你自己的编译器和虚拟机实现。 JVM 将忽略自己不认可的属性。
以上是关于 Javaclass 文件的一个基本结构的分析。主要是对书上关于这一章的总结,同时参考了 : http://hi.baidu.com/52dege/blog/item/f33a3cf4092491dbf3d3854f.html 等网上资料。
看一个 java classfile 有助于我们理解的实际例子:
代码 1 :
[java] view plaincopyprint?
public class StringTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String a = "aaabbb";
String b = "aaabbb";
System.out.println(a == b);
System.out.println(a.equals(b));
}
}
public class StringTest { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub String a = "aaabbb"; String b = "aaabbb"; System.out.println(a == b); System.out.println(a.equals(b)); } }
运行结果为 :true true
代码 2 :
[java] view plaincopyprint?
public class StringTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String a = "aaabbb";
String b = "aaa";
b += "bbb";
System.out.println(a == b);
System.out.println(a.equals(b));
}
}
public class StringTest { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub String a = "aaabbb"; String b = "aaa"; b += "bbb"; System.out.println(a == b); System.out.println(a.equals(b)); } }
运行结果为 :false true
关于代码 1 和代码 2 的解释:
Java 编译器在生成 class 文件的时候对代码里面定义的字符串都会作为一个字符串常量存放在常量池中。
对于代码 1 中的 String a = "aaabbb"; 和 String b = "aaabbb"; 预处理在编译处理后, a 和 b 都指向了常量池里的 ”aaabbb” ,所以 a==b 是 true.
对于代码 2 中的 String b = "aaa"; b += "bbb"; 编译处理后会在常量池里面生成 ”aaa” 和 ”bbb”, 同时, b += "bbb"; 语句会导致 Jvm 去重新创建一个 string 对象,相当于 b=new String(“aaabbb”); 自然, aaa==bbb 是 false 。这也是为什么不推荐使用加号来拼接字符串了。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2