Day7-堆,栈,方法区和GC

2017-08-23  本文已影响104人  我不是死胖子

Tips

JVM中

堆和栈对比

存什么

int a[] = new int[4];
new int[] 存放在堆, int a[] 存放在栈

Double a[] = new Double[10000000];
   Double qq = 3.1d;
   for (int i = 0; i < a.length; i++) {
       a[i] = qq.doubleValue();
   }

a[i] = qq.doubleValue;
a[i] = Double.valueOf(qq);
a[i] = new Double(qq.doubleValue);
所以此double类的值存在堆

独有/共享

异常

空间大小

执行效率

方法区

GC(Garabage Collection)

指的是堆中数据的回收, 首先堆可以划分为新生代和老年代


新生代继续划分为 Eden 和 Survivor Space(幸存区), Survivor Space 再被划分成 From 和 To



新对象首先被创建在 Eden, (如果对象过大,如数组,则直接放入老年代). 在 GC 中, Eden 会被移入Survivor Space. 直到对象熬过一定的Minor GC的次数, 会被移到老年代, 老年代用Major GC来清理

空间占比:

分代收集

新生代使用Minor GC, 老年代使用Major GC
Minor GC 和 Major GC 统称为 Full GC
所有的Minor GC 会触发全世界暂停 STW(stop-the-world), 停止应用程序的线程, 当然对于大多数应用,停顿的延迟可以忽略不计, 真相是大部分Eden区中的对象都能被认为是垃圾,所以不会存放到Survivor Space.
现在很多的GC机制都会清理永久代(静态方法区)

纯java代码无法泄漏栈空间, 它完全被JVM掌控, 但如果有其他资源依附在java对象上, 如native memory(DirectByteBuffer), file(fileInputStream), 那么当然自己关闭最合适

可达性检测

java减小GC开销 from

整理策略

清除会产生碎片,对内存的利用不是很好, 但是不代表整理比清除好, 毕竟整理慢, 比如CMSGC就是使用清除而不是整理的

思考一下复制和标记清除/整理的区别,为什么新生代要用复制?因为对新生代来讲,一次垃圾收集要回收掉绝大部分对象,我们通过冗余空间的办法来加速整理过程(不冗余空间的整理操作要做swap,而冗余只需要做move)。同时可以记录下每个对象的『年龄』从而优化『晋升』操作使得中年对象不被错误放到老年代。而反过来老年代偏稳定,我们哪怕是用清除,也不会产生太多的碎片,并且整理的代价也并不会太大。

作者:纳达丶无忌
链接:http://www.jianshu.com/p/c9ac99b87d56
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

寄存器

在计算机领域,寄存器是CPU内部的元件,它是有限存贮容量的高速存贮部件,可用来暂存指令、数据和地址。
寄存器分为通用寄存器和特殊寄存器。通用寄存器有 ax/bx/cx/dx/di/si,在大多数指令中可以任意选用,但也有一些规定某些指令只能用某个特定的「通用」寄存器;特殊寄存器有 bp/sp/ip 等,特殊寄存器均有特定用途。

在 Stack Frame 中,涉及到三种重要的特殊寄存器:

需要注意的是,不同架构的CPU,寄存器名称会添加不同的前缀来表示寄存器的大小。例如对于x86架构,字母「e」用作名称前缀,表示寄存器大小为32位;对于x86_64架构,字母「r」用作名称前缀,表示寄存器大小为64位。

举例

public void foo(){
  //do something...
  println("haha"); // <<<=== 在这儿设置breakpoint 1
}

public void bar(){
  foo();
}

main(){
  bar();
  println("hahaha"); // <<<=== 在这儿设置 breakpoint 2
}

当程序运行到breakponit1时,user stack 里会有三个frame
|
| main 函数的 frame-------------------
|
| bar 函数的 frame-------------------<<<=== %ebp
|
| foo 函数的 frame------------------- <<<===%esp
其中 esp 和 ebp 都是寄存器。 esp 指向stack 的顶(因为stack 向下生长,esp会向下走); ebp 指向当前frame的边界。
当程序继续执行到brekapoing 2的时候stack 大概是这样的:
|
-------------------<<<=== %ebp
|
| main 函数的 frame------------------- <<<===%esp
也就是说当一个函数执行结束后,它对应的call frame就被销毁了。(其实就是esp 和 ebp分别以东,但是内存地址中的数据只有在下一次写的时候才被覆盖。)
说了这么多,终于该说什么东西放在stack 上什么东西放在heap 上了。
最直白的解释:

public void foo(){
  int i = 0; // <= i 的值存在stack上,foo()的call frame 里。
  Object obj = new Object(); // object 对象本身存在heap 里, foo()的call frame 里存该对象的地址。
}

图片引自CMU15-213的课件
https://www.cs.cmu.edu/~213/

作者:雷博
链接:https://www.zhihu.com/question/29833675/answer/45811216
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


数据结构中

栈是先进后出的结构

参考

上一篇 下一篇

猜你喜欢

热点阅读