heap
和
stack
有什么区别。栈是一种线形集合,其添加和删除元素的操作应在同一段完成。栈按照后进先出的方式进行处理。堆是栈的一个组成元素
.
堆存储
:heapstorage
堆存储分配:
heapstorage allocation
堆存储管理:
heap
storage management
栈编址:
stack
addressing
栈变换:
stack
transformation
栈存储器:
stack
memory
栈单元:
stack cel
在
JVM
中,内存分为两个部分,
Stack
(栈)和
Heap
(堆),这里,我们从
JVM
的内存管理原理的角度来认识
Stack
和
Heap
,并通过这些原理认清
Java
中静态方法和静态属性的问题。
一般,
JVM
的内存分为两部分:
Stack
和
Heap
。
Stack
(栈)是
JVM
的内存指令区。
Stack
管理很简单,
push
一定长度字节的数据或者指令,
Stack
指针压栈相应的字节位移;
pop
一定字节长度数据或者指令,
Stack
指针弹栈。
Stack
的速度很快,管理很简单,并且每次操作的数据或者指令字节长度是已知的。所以
Java
基本数据类型,
Java
指令代码,常量都保存在
Stack
中。
Heap
(堆)是
JVM
的内存数据区。
Heap
的管理很复杂,每次分配不定长的内存空间,专门用来保存对象的实例。在
Heap
中分配一定的内存来保存对象实例,实际上也只是保存对象实例的属性值,属性的类型和对象本身的类型标记等,并不保存对象的方法(方法是指令,保存在
Stack
中)
,
在
Heap
中分配一定的内存保存对象实例和对象的序列化比较类似。而对象实例在
Heap
中分配好以后,需要在
Stack
中保存一个
4
字节的
Heap
内存地址,用来定位该对象实例在
Heap
中的位置,便于找到该对象实例。
由于
Stack
的内存管理是顺序分配的,而且定长,不存在内存回收问题
;而
Heap
则是随机分配内存,不定长度,存在内存分配和回收的问题;因此在
JVM
中另有一个
GC
进程,定期扫描
Heap
,它根据
Stack
中保存的
4
字节对象地址扫描
Heap
,定位
Heap
中这些对象,进行一些优化(例如合并空闲内存块什么的),并且假设
Heap
中没有扫描到的区域都是空闲的,统统
refresh
(实际上是把
Stack
中丢失了对象地址的无用对象清除了),这就是垃圾收集的过程;关于垃圾收集的更深入讲解请参考
51CTO
之前的文章《
JVM
内存模型及垃圾收集策略解析》。
JVM
的体系结构
我们首先要搞清楚的是什么是数据以及什么是指令。然后要搞清楚对象的方法和对象的属性分别保存在哪里。
1
)方法本身是指令的操作码部分,保存在
Stack
中;
2
)方法内部变量作为指令的操作数部分,跟在指令的操作码之后,保存在
Stack
中(实际上是简单类型保存在
Stack
中,对象类型在
Stack
中保存地址,在
Heap
中保存值);上述的指令操作码和指令操作数构成了完整的
Java
指令。
3
)对象实例包括其属性值作为数据,保存在数据区
Heap
中。
非静态的对象属性作为对象实例的一部分保存在
Heap
中,而对象实例必须通过
Stack
中保存的地址指针才能访问到。因此能否访问到对象实例以及它的非静态属性值完全取决于能否获得对象实例在
Stack
中的地址指针。
非静态方法和静态方法的区别:
非静态方法有一个和静态方法很重大的不同:非静态方法有一个隐含的传入参数,该参数是
JVM
给它的,和我们怎么写代码无关,这个隐含的参数就是对象实例在
Stack
中的地址指针。因此非静态方法(在
Stack
中的指令代码)总是可以找到自己的专用数据(在
Heap
中的对象属性值)。当然非静态方法也必须获得该隐含参数,因此非静态方法在调用前,必须先
new
一个对象实例,获得
Stack
中的地址指针,否则
JVM
将无法将隐含参数传给非静态方法。
静态方法无此隐含参数,因此也不需要
new
对象,只要
class
文件被
ClassLoader
load
进入
JVM
的
Stack
,该静态方法即可被调用。当然此时静态方法是存取不到
Heap
中的对象属性的。
总结一下该过程:当一个
class
文件被
ClassLoader
load
进入
JVM
后,方法指令保存在
Stack
中,此时
Heap
区没有数据。然后程序技术器开始执行指令,如果是静态方法,直接依次执行指令代码,当然此时指令代码是不能访问
Heap
数据区的;如果是非静态方法,由于隐含参数没有值,会报错。因此在非静态方法执行前,要先
new
对象,在
Heap
中分配数据,并把
Stack
中的地址指针交给非静态方法,这样程序计数器依次执行指令,而指令代码此时能够访问到
Heap
数据区了。
静态属性和动态属性:
前面提到对象实例以及动态属性都是保存在
Heap
中的,而
Heap
必须通过
Stack
中的地址指针才能够被指令(类的方法)访问到。因此可以推断出:静态属性是保存在
Stack
中的,而不同于动态属性保存在
Heap
中。正因为都是在
Stack
中,而
Stack
中指令和数据都是定长的,因此很容易算出偏移量,也因此不管什么指令(类的方法),都可以访问到类的静态属性。也正因为静态属性被保存在
Stack
中,所以具有了全局属性。
在
JVM
中,静态属性保存在
Stack
指令内存区,动态属性保存在
Heap
数据内存区。
分享到:
相关推荐
"Java 中堆(heap)和堆栈(stack)的区别" Java 中堆(heap)和堆栈(stack)是两个不同的内存区域,分别用于存储不同的数据类型和对象。堆栈(stack)是 Java 中的一种内存区域,用于存储基本类型的变量和对象的...
Java内存主要分为三个区域:堆(Heap)、栈(Stack)和方法区(Method Area),其中堆是用于存储对象实例的主要区域,当堆空间不足时,就会抛出`OutOfMemoryError: Java heap space`。 1. **调整JVM堆大小**:可以...
在IT领域,尤其是在操作系统与编程语言的运行时环境中,“运行时堆和栈”(The Run-time Heap and Stack)是理解程序内存管理的核心概念。本文旨在深入解析这一主题,结合提供的部分文档内容,详细阐述堆和栈的区别...
堆(heap)与栈(stack)是计算机内存管理中的两种基本数据结构,用于存储程序运行时产生的临时变量。在C语言中,这两种内存区域有非常明确的区分,对于理解程序的内存分配和回收具有重要意义。 首先,栈是一种特殊...
Java虚拟机(JVM)是Java应用程序的运行环境,它负责执行字节码并管理内存...通过上述方法,可以有效地预防和解决`java.lang.OutOfMemoryError: Java heap space`问题,优化JVM内存管理,提升应用程序的稳定性和性能。
Java堆空间(Heap Space)是Java虚拟机(JVM)管理的...CSDN_NET.mht》和《Java heap space 解决方法.txt》可能提供了更详细的步骤和具体案例来帮助理解并解决这个问题。建议仔细阅读这些资料,结合实际情况进行调整。
Java内存主要分为堆(Heap)、栈(Stack)、方法区(Method Area)、程序计数器(PC Register)和本地方法栈(Native Method Stack)五大部分: 1. **堆**:Java对象主要存储在堆中,它是所有线程共享的一块区域。...
Java内存分为堆(Heap)、方法区(Method Area)、栈(Stack)、本地方法栈(Native Method Stack)和程序计数器(PC Register)五大部分。HeapAnalyzer主要关注的是堆内存,特别是新生代(Young Generation)、老...
"深入Java虚拟机中的Stack和Heap" 在Java虚拟机(JVM)中,内存分为两个部分:Stack(栈)和Heap(堆)。Stack是JVM的内存指令区,管理很简单,push一定长度字节的数据或者指令,Stack指针压栈相应的字节位移;pop...
在一些平台上,在有些情况下,javacore也被称为javadump,它包含jvm和应用程序相关的在特定时刻的一些诊断信息,如操作系统,应用程序环境,线程,native stack本地堆,锁,和内存的信息。在生成heapdump文件的时候...
Java程序运行在JVM上,JVM将内存划分为几个区域,包括堆内存(Heap)、栈内存(Stack)、方法区(Method Area)、程序计数器(PC Register)和本地方法栈(Native Method Stack)。其中,堆内存是所有线程共享的一块...
"深入Java虚拟机:JVM中的Stack和Heap" Java虚拟机(JVM)是一种运行Java字节码的虚拟机环境,它具有自己的内存管理机制。JVM的内存分为两个部分:Stack(栈)和Heap(堆)。 Stack(栈)是JVM的内存指令区,管理...
在Java中,内存主要分为两个区域:栈(Stack)和堆(Heap),以及垃圾回收机制(Garbage Collection)。 栈是程序执行过程中的临时数据存储区域,主要用于存储基本类型(如int、char)和对象的引用。每当一个方法被...
### JStack和Java Thread Dumps分析 #### 一、引言 在Java应用程序开发与维护过程中,时常会遇到性能瓶颈或死锁等问题。这些问题往往难以定位,尤其当系统处于高负载下时,更是如此。此时,`JStack`工具便显得尤为...
JAVA-OPTS 变量的设置对 Java 应用程序的性能和稳定性具有重要影响。 在设置 JAVA-OPTS 变量时,需要注意以下几个方面: 1. -server:这个参数一定要作为第一个参数,否则可能会导致性能下降。在多个 CPU 时性能佳...
常见的内存错误包括`java.lang.OutOfMemoryError: Heap space`(堆空间不足)、`java.lang.OutOfMemoryError: PermGen space`(方法区空间不足)和`java.lang.StackOverflowError`(栈溢出)。这些错误通常由于物理...
Java 中的内存溢出和解决方案 Java 中的内存溢出是一种常见的错误,可能会导致程序崩溃或hang死。了解 Java 中的内存溢出原因和解决方案是非常重要的。本文将介绍 Java 中的几种常见的内存溢出和解决方案。 1.JVM...
- 字符串常量和this指针分别在Stack和Heap中有不同的存储方式。 - 数组既可以看作对象,也可以看作基本数据类型数组,因此在Stack中分配地址,在Heap中分配空间。 6. C/C++内存管理: - C/C++的内存管理分为堆、...
Java内存模型(JMM)是Java虚拟机规范中的一部分,它定义了线程如何共享和访问内存中的数据,包括堆和栈。理解JMM对于优化应用程序性能和避免内存泄漏至关重要。 1. **JMM(Java Memory Model)**: - JMM确保在...
堆(Heap)和栈(Stack)是JAVA中两种重要的内存区域。堆是用于存储所有JAVA对象和数组的空间,其大小动态调整,由垃圾回收器管理。栈则是用于存储局部变量和方法调用的信息,每个线程都有自己的私有栈空间。 ### 8...