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 #2 = String # 21 #3 = Fieldref # 22 .# 23 #4 = Methodref # 24 .# 25 #5 = Class # 26 #6 = Methodref # 5 .# 27 #7 = Fieldref # 8 .# 28 #8 = Class # 29 #9 = Class # 30 #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 #21 = Utf8 aa #22 = Class # 31 #23 = NameAndType # 32 :# 33 #24 = Class # 34 #25 = NameAndType # 35 :# 36 #26 = Utf8 java/lang/String #27 = NameAndType # 12 :# 36 #28 = NameAndType # 10 :# 11 #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 4 : return LineNumberTable: line 1 : 0 void hello(); flags: Code: stack=3 , locals= 3 , args_size= 1 0 : ldc # 2 2 : astore_1 3 : getstatic # 3 6 : aload_1 7 : invokevirtual # 4 10 : new # 5 13 : dup 14 : ldc # 2 16 : invokespecial # 6 19 : astore_2 20 : getstatic # 3 23 : aload_2 24 : invokevirtual # 4 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 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为局部变量,且为引用类型,对内存优化并没有任何实在意义。