通常都看到书籍文章中,Stack 的中文翻译一会儿说是”堆栈“。一会儿又有人说”堆“是堆,”栈“是栈 ...
把简单的东西弄得绕来绕去,头也会大。所以还是直接用英文更准确一些。Java 和 C 关于它们的概念都是相通的。
Stack有两个概念。
首先它是一种 Abstract Data Type。 就是常说的 Last In First Out 数据模型。但是当把 Stack 和 Heap 放在一起的时候,我们通常指的是另外一个概念,指的是 Hardware Stacks ,是对 memory 的分配和使用方式。
在 Java 中的 memory 的使用,通常有以下几种:
- Register:我们在程序中无法控制
- Stack :存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中
- Heap :存放用new产生的数据。(Java和C对Heap处理不同,Java由垃圾收集器自动管理)
- Static Field :存放在对象中用static定义的静态成员
- Constant Pool:存放常量
- Non-RAM : (随机存取存储器)存储:硬盘等永久存储空间
Stack 是从高地址往下分配。 只有 push 和 pop 两个操作,可能会碰到的问题是,当指针指向低于最小值的时候,a stack underflow occurs. 反之,如果大于乐最大地址值,a stack overflow occurs. 它的优点是速度快,有数据共享的功能。它是在对象实例化的时候分配的空间,通过 new 创建; java中不需要显示释放,由垃圾收集器自动管理。
直接看例子最容易理解:
对于String这个类来说,可由两个方式建立:
String s = new String ("ABC");
“s” 在Stack里,而但"ABC" 在 Heap 中会不断地创建新的对象
String s = "ABC"; String b = "A" + "BC";
"S" 和 "b" 都在 Stack 中。“ABC” , “A” 和 “BC” 在 Constant Pool 中。然后 JVM 会把它们优化到同一个 “ABC” 。所以 S 和 B 指向同一个位置。
在 JAVA 的 JVM 中,通常把 Memory 的概念简化为:
1. Heap Memory
-Xmx<size> - to set the maximum Java heap size -Xms<size> - to set the initial Java heap size
2. Non Heap Memory
-XX:MaxPermSize=128m
3. Other
再来看一个C的例子:
//main.cpp int a = 0; 全局初始化区 char *p1; 全局未初始化区 main() { int b; 栈 char s[] = "abc"; 栈 char *p2; 栈 char *p3 = "123456"; 123456在常量区,p3在栈上。 static int c =0; 全局(静态)初始化区 p1 = (char *)malloc(10); p2 = (char *)malloc(20); 分配得来得10和20字节的区域就在堆区。 strcpy(p1, "123456"); 123456放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。 }