栈
栈的特点:先进后出
队列的特点:先进后出(FIFO:First Input First Output)
方便记忆:喝多了吐是栈,吃多了拉是队列
为什么main方法先执行,最后结束?
因为栈的特点,先进后出
栈:栈内存,管控程序的运行,生命周期和线程同步
线程结束,栈内存就释放,对于栈来说,不存在垃圾回收问题
栈:八大基本类型、对象引用、实例的方法
栈运行原理:栈帧
栈满:StackOverflowError
程序中正在执行的方法,一定在栈的顶部
堆
Heap,一个JVM只有一个堆内存,堆内存的大小是可以调节的
类加载器读取了类文件后,一般会把什么东西放到堆中?
类,方法,常量,变量,以及我们所有引用的实际的对象
堆内存中还有细分的区域:
1.新生区(包括伊甸园区) Young/New
新生区包括伊甸园区及幸存区
轻GC
2.老年区 old
重GC Full GC
3.永久存储区 Perm
GC垃圾回收主要都在伊甸园区及老年区
如果内存满了,会报OOM(OutofMemoryError:Java Heap space)错误,因为堆内存不够
在JDK8以后,永久存储器称为元空间
新生区
新生区是类诞生和成长的地方,甚至也是类死亡的地方
新生区有三个部分:
伊甸园区
-->所有的对象都是在伊甸园区new出来的
幸存者0区
幸存者1区
如果幸存者区都满了,则会进入养老区,启动重GC,并且会清空当前伊甸园区、幸存者区所有数据
老年区
一般而言,绝大多数的对象都是临时对象,不会进入到老年区
永久区
永久区是常驻内存的,用来存放JDK自身携带的Class对象、Interface、元数据,etc,存储的是Java运行时的一些环境或类信息,这个区域不存在垃圾回收,关闭vm虚拟就会释放这个区域的内存
什么时候会使用永久区?
一个启动类,加载了大量的第三方jar包
tomcat部署了太多的应用
动态生成了大量的反射类
...
它们会不断的被加载,直到内存满了,就报OOM的错误
JDK1.6之前:永久代,常量池在方法区里
JDK1.7:永久代,但是慢慢退化了,去永久代,常量池在堆中
JDK1.8之后:无永久代,常量池在元空间
元空间逻辑上存在,物理上不存在
默认情况下,分配给虚拟机的总内存是电脑内存的1/4,Jvm的初始化总内存是1/64
如果报OOM的错,可以先去尝试调整分配的栈内存大小,调整完了之后仍然报错,则说明是我们代码的问题