JVM内存结构划分
JVM内存结构划分
栈
栈(Stack)是一种基本的数据结构,用于按照“后进先出”(Last In First Out,LIFO)的原则存储和访问数据。以下是栈的一些关键概念和特性:
基本操作:
- 压栈(Push):将一个元素添加到栈顶。
- 弹栈(Pop):移除栈顶元素,并返回它。
- 查看栈顶(Peek/Top):查看但不移除栈顶元素。
实现方式:
- 栈可以用数组或链表来实现。数组实现提供了基本的索引访问,而链表实现则允许动态大小调整。
*时间复杂度**:
- 压栈和弹栈操作通常都是O(1)时间复杂度,即常数时间内完成。
空间复杂度:
- 栈的空间复杂度取决于其最大容量。如果栈大小固定,则空间复杂度为O(n),其中n是栈的大小;如果栈大小可变,则空间复杂度为O(1),即不考虑最坏情况下的容量。
应用场景:
- 表达式求值和运算符优先级检查。
- 函数调用时的返回地址和局部变量存储(调用栈)。
- 撤销操作(Undo)的实现。
- 括号匹配检查。
- 深度优先搜索(DFS)算法的实现。
栈的遍历:
- 通常从栈顶开始,按照压栈的逆序进行遍历。
数据结构特性:
- 栈是一种线性数据结构,但它只允许在一端(栈顶)进行操作。
栈溢出:
- 当栈空间被占满,无法再压入新元素时,称为栈溢出,可能会抛出异常(例如Java中的
StackOverflowError
)。
public class StackArrayImpl {
private int[] stack;
private int top;
private int capacity;
// 构造函数,初始化栈的大小
public StackArrayImpl(int size) {
capacity = size;
stack = new int[capacity];
top = -1; // 栈为空时,栈顶索引设置为-1
}
// 压栈操作
public void push(int value) {
if (top >= capacity - 1) {
System.out.println("Stack Overflow. Cannot push more elements.");
return;
}
stack[++top] = value; // 栈顶索引递增后,将元素放入栈顶位置
}
// 弹栈操作
public int pop() {
if (top == -1) {
System.out.println("Stack Underflow. Cannot pop from an empty stack.");
return -1; // 栈为空时返回-1或其他错误代码
}
return stack[top--]; // 返回栈顶元素,并递减栈顶索引
}
// 查看栈顶元素
public int peek() {
if (top == -1) {
System.out.println("Stack is empty. Nothing to peek.");
return -1; // 栈为空时返回-1或其他错误代码
}
return stack[top]; // 返回栈顶元素但不移除
}
// 判断栈是否为空
public boolean isEmpty() {
return top == -1;
}
// 判断栈是否已满
public boolean isFull() {
return top == capacity - 1;
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
StackArrayImpl stack = new StackArrayImpl(5); // 创建一个大小为5的栈
// 压栈操作
stack.push(1);
stack.push(2);
stack.push(3);
// 查看栈顶元素
System.out.println("Top element is: " + stack.peek());
// 弹栈操作
System.out.println("Popped element is: " + stack.pop());
// 判断栈是否为空
System.out.println("Is the stack empty? " + stack.isEmpty());
}
}
在这个示例中,StackArrayImpl
类使用一个整型数组stack
来存储栈中的元素,top
变量用于追踪栈顶的位置。构造函数初始化栈的大小,push
方法用于向栈中添加元素,pop
方法用于移除并返回栈顶元素,peek
方法用于查看栈顶元素而不移除它。isEmpty
和isFull
方法分别用于判断栈是否为空和是否已满。
堆
堆(Heap)是一个非常重要的内存区域,用于存储对象实例和数组
内存分配:ava堆用于动态内存分配,几乎所有的对象实例和数组都是在这里分配的。
堆配置:可以使用JVM参数(如-Xms
和-Xmx
)来设置堆的初始大小和最大大小。
堆空间监控:可以使用JMX(Java Management Extensions)和其他监控工具来实时监控堆的使用情况。
public class MinHeap {
private int[] heap;
private int size; // 当前堆中元素的数量
private int capacity; // 堆的最大容量
// 构造函数,初始化堆的大小
public MinHeap(int capacity) {
this.capacity = capacity;
this.heap = new int[capacity];
this.size = 0;
}
// 向堆中添加元素
public void add(int value) {
if (size >= capacity) {
System.out.println("Heap Overflow. Cannot add more elements.");
return;
}
heap[size] = value;
swim(size); // 上浮调整
size++;
}
// 访问堆顶元素
public int peek() {
if (size == 0) {
System.out.println("Heap is empty.");
return Integer.MIN_VALUE; // 或者抛出异常
}
return heap[0];
}
// 移除堆顶元素
public int remove() {
if (size == 0) {
System.out.println("Heap is empty.");
return Integer.MIN_VALUE; // 或者抛出异常
}
int removed = heap[0];
heap[0] = heap[size - 1];
size--;
sink(0); // 下沉调整
return removed;
}
// 上浮操作,保持堆的有序性
private void swim(int index) {
while (index > 0 && heap[parent(index)] > heap[index]) {
swap(parent(index), index);
index = parent(index);
}
}
// 下沉操作,保持堆的有序性
private void sink(int index) {
while (leftChild(index) < size) {
int j = leftChild(index);
if (j + 1 < size && heap[j] > heap[j + 1]) {
j++;
}
if (heap[index] < heap[j]) {
swap(index, j);
index = j;
} else {
break;
}
}
}
// 交换堆中的两个元素
private void swap(int i, int j) {
int temp = heap[i];
heap[i] = heap[j];
heap[j] = temp;
}
// 获取父节点的索引
private int parent(int index) {
return (index - 1) / 2;
}
// 获取左子节点的索引
private int leftChild(int index) {
return 2 * index + 1;
}
// 获取右子节点的索引
private int rightChild(int index) {
return 2 * index + 2;
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
MinHeap minHeap = new MinHeap(10); // 创建一个容量为10的最小堆
// 向堆中添加元素
minHeap.add(4);
minHeap.add(1);
minHeap.add(3);
minHeap.add(2);
// 访问堆顶元素
System.out.println("Top element is: " + minHeap.peek());
// 移除堆顶元素
System.out.println("Removed element is: " + minHeap.remove());
}
}
在这个示例中,MinHeap
类使用一个整型数组heap
来存储堆中的元素。size
变量用于追踪当前堆中元素的数量,而capacity
表示堆的最大容量。add
方法用于向堆中添加新元素,并调用swim
方法来维护堆的有序性。peek
方法用于返回堆顶元素,而remove
方法用于移除并返回堆顶元素,并调用sink
方法来维护堆的有序性。swim
和sink
操作确保了堆的最小堆性质。
作者:静默虚空
欢迎任何形式的转载,但请务必注明出处。
限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术