javac Hello.java
public class Hello{
static int num = 1;
void hello(){
String s = "aa";
System.out.println(s);
String s2 = new String("aa");
System.out.println(s2);
}
}
javap -v Hello.class
Classfile /G:/workspace/Projects/Golang/Hello.class
Last modified 2014-12-30; size 527 bytes
MD5 checksum e84276bb63ef1ea05d80fa07852dfce2
Compiled from "Hello.java"
public class Hello
SourceFile: "Hello.java"
minor version: 0
major version: 51
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #9.#20 // java/lang/Object."<init>":()V
#2 = String #21 // aa
#3 = Fieldref #22.#23 // java/lang/System.out:Ljava/io/PrintStream;
#4 = Methodref #24.#25 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Class #26 // java/lang/String
#6 = Methodref #5.#27 // java/lang/String."<init>":(Ljava/lang/String;)V
#7 = Fieldref #8.#28 // Hello.num:I
#8 = Class #29 // Hello
#9 = Class #30 // java/lang/Object
#10 = Utf8 num
#11 = Utf8 I
#12 = Utf8 <init>
#13 = Utf8 ()V
#14 = Utf8 Code
#15 = Utf8 LineNumberTable
#16 = Utf8 hello
#17 = Utf8 <clinit>
#18 = Utf8 SourceFile
#19 = Utf8 Hello.java
#20 = NameAndType #12:#13 // "<init>":()V
#21 = Utf8 aa
#22 = Class #31 // java/lang/System
#23 = NameAndType #32:#33 // out:Ljava/io/PrintStream;
#24 = Class #34 // java/io/PrintStream
#25 = NameAndType #35:#36 // println:(Ljava/lang/String;)V
#26 = Utf8 java/lang/String
#27 = NameAndType #12:#36 // "<init>":(Ljava/lang/String;)V
#28 = NameAndType #10:#11 // num:I
#29 = Utf8 Hello
#30 = Utf8 java/lang/Object
#31 = Utf8 java/lang/System
#32 = Utf8 out
#33 = Utf8 Ljava/io/PrintStream;
#34 = Utf8 java/io/PrintStream
#35 = Utf8 println
#36 = Utf8 (Ljava/lang/String;)V
{
static int num;
flags: ACC_STATIC
public Hello();
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 1: 0
void hello();
flags:
Code:
stack=3, locals=3, args_size=1
0: ldc #2 // String aa
2: astore_1
3: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
6: aload_1
7: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
10: new #5 // class java/lang/String
13: dup
14: ldc #2 // String aa
16: invokespecial #6 // Method java/lang/String."<init>":(Ljava/lang/String;)V
19: astore_2
20: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
23: aload_2
24: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
27: return
LineNumberTable:
line 4: 0
line 5: 3
line 6: 10
line 7: 20
line 8: 27
static {};
flags: ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: iconst_1
1: putstatic #7 // Field num:I
4: return
LineNumberTable:
line 2: 0
}
static {};
静态初始化代码;
String s = “aa”;
和
new String(“aa”);
从同一常量池出获取值
Java的8中基本类型:boolen,char,byte,short,int,long,float,double,基本类型的值被存储在栈中,因为这样更快。
栈:
1、当定义 int a = 10 时,编译器会在栈中分配4个字节空间来存放值(10),内存地址(0x0001)。
2、创建变量a, a的内存地址(0x0005),
存放(10)的地址(0x0001)。
引用(10)。
3、再定义 int b = 10 时,b的内存地址(0x0006),
同样存放(10)的地址(0x0001)。
引用(10)。
所以栈中的数据是共享的。
堆:
内存池,存储所有使用new出来的Java对象。
创建一个对象通常包括两个步骤:
1、对象声明(即创建对象引用)。
2、实例化(即为对象在堆中分配存储空间)。
常量
堆,方法区,栈和本地方法栈
堆(-Xms和-Xmx)调节
new出来的对象实例,都在堆上分配内存。
方法区(-XX:PermSize和-XX:MaxPermSize)调节
存放:类、静态变量和常量。
静态变量、常量、类太多,永久带内存可能不够。
栈和本地方法栈(-Xss)调节
存放:局部变量、参数、操作,方法出口等与方法相关的信息。
方法调用层次太多(递归), 该区内存可能不够。
===============================================================
(heap, stack, data-seg, code-seg)
heap:–>new出来对象。
stack:–局部变量,用来计算的。
data-seg:–>静态变量、字符串常量
code-seg:–>代码
===============================================================
public void print(){
Object o = new Object();
}
这里这里程序会创建两个对象内存空间:
1、new Object()存在堆中。
2、o引用,存在栈中。
堆中的内存是由GC来管理回收的。(程序中没有对该对象存在引用)
栈中的内存是当方法的栈帧运行完后就释放的(引用占4个字节)。
程序运行时涉及:(指令栈,本地变量区、操作数区)
public void print(){
Integer l;
for (int i=1; i < 3; i++) {
l = 2;
}
}
与
public void print(){
for (int i=1; i < 3; i++) {
Integer l = 2;
}
}
后者Integer l 在同一goto指令内,栈对象都是复用的,刻意写成前者,对内存优化并没有任何实在意义。
用来o后设置 为o=null。
在同一方法栈内,o为局部变量,且为引用类型,对内存优化并没有任何实在意义。