目录
- 1.栈
- 1-1.栈帧
- 1-2.栈帧的组成
- 2.堆
- 2-1.对象的组成
- 3.本地方法栈
- 4.程序计数器
- 5.方法区
- <font color="red">如<font color="orange">果<font color="#FFEB05">你<font color="green">也<font color="skyblue">想<font color="blue">学<font color="purple">习<font color="black">:黑客&网络安全
- 在这里领取:
- 这个是我花了几天几夜自整理的<font color="red">最新最全网安学习资料包<font color="red"><font color="black">免费共享给你们,其中包含以下东西:
- 1.学习路线&职业规划
- 2.全套体系课&入门到精通
- 3.黑客电子书&面试资料
1.栈
栈是连续的空间,先进后出,从技术上说,栈就是CPU寄存器里的某个指针所指向的一片内存区域。这里所说的“某个指针”通常位于x86/x64平台的ESP寄存器/RSP寄存器,以及ARM平台的SP寄存器。
栈会给每个线程都分配一个栈帧,java中8大基本类型和对象的引用都是在栈内存中分配,在栈里同名值是共享内存的,比如:
int a=3;
int b=3;//a,b指向的是同一个"3",但是和对象的引用不同,改变a的值并不会影响b
a=4;//使a=4,如果栈里面没有"4",那就会重新创一个"4"
对象的引用一旦调用了new关键字,他就会在堆内存开辟一个存储空间。
Person person;//这个person就是对象的引用
person = new Person();//这里用new关键字,在堆里面给实例对象分配一块内存
1-1.栈帧
栈帧也叫过程活动记录,是编译器用来实现过程/函数调用的一种数据结构。
压栈和弹栈:就是入栈和出栈
1-2.栈帧的组成
之前看过一篇文章总结的很好,下面附上超链接:栈帧
2.堆
1.Java中所有对象的存储空间都是在堆中分配的,简单来说就是:
引用在栈,实例在堆,下面用一个常见的例子来说明
String str = "haha";
String str1 = "haha";
String str2 = new String("haha");
String str3 = new String("haha");
str == str1;//true
str == str2;//false
str2 == str3;//false
上面的str和str1没有使用new创建对象,"haha"属于常量,在常量池,共用一个“haha”,同一块空间
str2和str3都用了new关键字,开辟了两块空间,所以是不同的对象。
2.一个JVM只有一个堆内存,堆内存的大小是可以调节的,堆存储的全是对象
2-1.对象的组成
而对象在内存中的存储布局分为三部分:
A.对象头
java里面用两个字来表示对象头,一个是Mark Word,一个是Klass pointer(Class MetaData Address)
(1)Mark Word(包含了自身运行时数据)
包括锁状态(lock,bkased_lock等),hashcode,GC分代年龄(age),线程持有的锁等… …
(2)Klass pointer(就是一个指针)
虚拟机通过这个指针来确定对象是哪个类的实例
64位虚拟机的对象组成(有锁无锁):
B.实例数据
就是你在类里面写的东西
C.对齐填充
JVM要求对象起始地址必须是8字节的整数倍(8字节对齐),所以不够8字节就由这部分来补充。
3.堆内存分为三个区域:
-
新生代(发生Minor GC)新生代采取淘汰机制,活不下去的就被轻GC回收
(1)伊甸园:
梦开始的地方,这个区域人满了,大家就要进行Minor GC,活下来的去幸存区(2)幸存区:
幸存区分为两块,from区和to区。那为什么要分为两块呢?因为在新生代会发生 Minor GC(轻度垃圾回收),15次回收还没有淘汰的会进入老年代,进行 Full GC(重度垃圾回收),而Full GC花费的时间和资源是远大于Minor GC的,因此我们将幸存区分为两块,在from和to之间用 四大算法 中的复制来进行筛选机制。
新创建的对象一般会被分配到伊甸区,经过一次Minor GC后,如果对象还存活,就会被移到Survivor区。from区的对象如果继续存活,且能够被另一块幸存区to区容纳,则使用复制算法将这些仍然存活的的对象复制到另一块幸存区to区中,然后清理使用过的Eden和from区(下一次分配就从to区开始,to区成为下一次GC的from区),且这些对象的年龄设置为1,以后对象在幸存区每经历一次Minor GC,对象的年龄就会+1,当对象的年龄到达某个阈值的时候,这些对象就会进入老年代。(阈值默认是15,可以通过-XX:MaxTenuringThreshhold来设定对象在新生代在存活的次数)
ABC经过一次Minor GC还存活进入幸存from区,下次Minor GC幸存者被复制到to区 然后清空from区,将to区变成新的from区,继续筛选,存活15次的进入老年代。
为什么要进行十五次筛选呢?
因为对象头采用四个字节来存放GC的信息:二进制1111刚好对应十进制的15. -
老年代(发生Full GC)
标记清除算法:标记要回收的对象统一回收。
和标记整理算法:标记要回收的对象,向同一端移动,移出边界的对象。 -
永久代(1.8后改为元空间)
此区域常驻内存,用来存放JDK自身携带的Class对象,Interface元数据,此区域不存在垃圾回收,关闭JVM时永久代自动关闭
1.6之前:永久代,常量池在5.方法区
1.7:永久代,常量池在堆中
1.8:无永久代
3.本地方法栈
Java刚开始的时候底层是用c实现的,后面逐渐演变为新语言Java后,仍然保留了一些c里面的方法,而本地方法区就是用来存这些方法的。这些方法的使用需要Native关键字
4.程序计数器
java中的程序计数器是一块比较小的内存空间,它是当前线程字节码执行的行号指示器。
5.方法区
和堆一样,线程共享,为了和堆区分,也称为非堆
如果你也想学习:黑客&网络安全
在这里领取:
这个是我花了几天几夜自整理的最新最全网安学习资料包免费共享给你们,其中包含以下东西:
1.学习路线&职业规划