数据结构复习笔记(Data Structures & Algorithms in Java, 4th) --Memory Management (Heap & Stack)

ref: http://www.ccs.neu.edu/home/cbw/5600/slides/8_Free_Space_and_GC.pptx

这篇文章主要是复习Java虚拟机(JVM)内存的简要介绍。在 JVM中,内存分别供程序代码(Program Code)栈(Stack)未使用的内存(Free Memory)堆(Heap)使用,如下图。所以接下来,我们会依序介绍 JVM在进行内存管理时,需要使用的几个数据结构。


Stacks
在JVM中的 Stack,有 Java 方法栈(method stack)及运算栈(Operand stack),分别用来管理程序执行顺序、管理变量还有执行运算的结果。比如说当执行下面代码的时候:

	public static void main(String[] args) {
		int i = 15;
		foo(i); // 假设这里 PC(Program Counter) = 14

	}

	private static void foo(int i) {
		int k = 6;
		bbb(k); // PC = 216
	}

	private static void bbb(int m) {  // PC = 320
		k++;
	}
在 Java 内存中其实是这样的:

一个方法在Method Stack需要 Frame来保存方法的Program Counter(PC) -保存著执行的内存位置及本地变量(Local Variables),而遇到程序内有子程序时,便另外产生一个Frame,并「压进(Push)」 Method Stack 中。直到需要执行时 PC自动加一,执行该内存地址的程序。另外,在这里要顺便介绍一下 Call-By-Value,它指的是目前的变量被当作方法参数传进被呼叫的方法里。简单的说,当使用 Call-By-Value的时候,如果参数是 primitive variable,那方法执行后,父方法的中的变量值依然不变;如果传进去的是一个对象,则对象内的值可以改变,所指向的内存位置则不能改变。例子如下: 

	public static void main(String[] args) {
		int i = 15;
		foo(i);
		int[] j = new int[2];
		j[0] = 15;
		System.out.println("Before calling foo: " + Arrays.toString(j));
		foo(j);
		System.out.println("After calling foo: " + Arrays.toString(j));
		System.out.println("===========================================");
		System.out.println("Before calling foo2: " + Arrays.toString(j));
		foo2(j);
		System.out.println("After calling foo2: " + Arrays.toString(j));
	}

	private static void foo2(int[] array) { // 此方法试图改变所指向的内存位置
		array = new int[3];
		array[0] = 1;
		array[1] = 2;
		array[2] = 3;
	}

	private static void foo(int[] array) { // 此方法改变数组对象的值
		array[0] = 0;
	}

运算桟(Operand Stack)负责的是一些数学运算功能,在这里用一简图代过:



Heap 内存管理
Java 程序里用 new 宣告产生的对象所使用的内存,便是从 Heap 中取得

int[] lists = new int[] // 所产生的对象在 Heap 内存区中
在JVM规范中要求 Heap 应要能快速的分配内存给新的对象,但没有明确规范要使用何种数据结构。free list 是维持可用内存常见的数据结构,它是链表(Linked List),分配、释放内存时,分别如下简图所示。




这种方式,便会产生内存碎片(Fragmentation)-即未被使用的内存片段分散在内存中,这样会导致使用内存时,计算机需要花费时间找到大小合适的区块或是一堆小块可用内存,但是却没一个符合我们需求的情况。


内存碎片(Fragmentation)
内存碎片有两种,一种是Internal Fragmentation指的是程序申请的内存大於实际的需求,比如说申请了大小为1000的数组,但是只使用了1000里面的其中5个。另一种为 External Fragmentation 指的是可用的内存散布在已使用的分存之间。

Heap的内存调用算法
best-fit algorithm:遍历找到大小最合适的可用内存块,理论上这算法可以帮我们减少碎片化,但是实际上却产生了更严重的碎片化问题, 因为碎片变得更细小了。
first-fit algorithm:使用 Free List 中第一个可用的内存块。优点是快,但是容易在 free list 前方产生许多内存碎片,未来在搜寻的时候便会降低速度。
next-fit algorithm:和 first-fit 差不多,但它不是从头开始找,它是从上次找到可用内存的地方开始往下一个找。next-fit 使碎片分布均匀,这样反而降低了调用大区块内存的效率。
worst-fit algorithm:使用最大的可用内存块。worst-fit 主要是用来解决 next-fit不容易找到大块内存的问题。






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值