4、java堆
主要用于分配对象实例和数组。
5、方法区
线程共享
用于存储已被虚拟机加载的类信息、常量、静态变量、即使编译后的代码等数据。
6、直接内存
直接内存并不是虚拟机运行时数据区的一部分。在NIO中,引入了一种基于通道和缓冲区的I/O方式,它可以使用native函数直接分配堆外内存,然后通过一个存储在java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。
7、栈
主要存放 动态链接方法、返回值、返回地址等信息
堆溢出
堆溢出原因莫过于对象太多导致。
2、栈溢出
根据JAVA虚拟机规范描述:
如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError
如果虚拟机在扩展栈时无法申请到足够的内存空间,将抛出OutOfMemoryError。
实验表明:
在单线程下,无论是由于栈帧太大还是虚拟机栈容量太小,当内存无法分配的时候,虚拟机抛出的都是StackOverflowError。
通过不断的建立新线程的方式可以产生内存溢出溢出。为每个线程的栈分配的内存越大,反而越容易产生内存溢出异常。
如果是建立过多线程导致的内存溢出,在不能减少线程数量或者更换64位虚拟机的情况下,就只能通过减少最大堆和减少栈容量来换取更多的线程。
假设32位windows系统虚拟机最大设为2G,虚拟机提供了参数来控制java堆和方法区这两部分最大值,剩余的内存为2G - Xmx- MaxPermSize,如果虚拟机本身进程内存大小不算在内,省下的内存就有虚拟机和本地方法栈瓜分了。每个线程分配到的栈容量越大,可以建立的线程数量自然就越少。
3、方法区溢出
当运行时常量池过大或者类过多时就会导致方法区溢出。
4、直接内存溢出
NIO的Buffer提供了一个可以不经过JVM内存直接访问系统物理内存的类——DirectBuffer。 DirectBuffer类继承自ByteBuffer,但和普通的ByteBuffer不同,普通的ByteBuffer仍在JVM堆上分配内存,其最大内存受到最大堆内存的限制;而DirectBuffer直接分配在物理内存中,并不占用堆空间,其可申请的最大内存受操作系统限制。
直接内存的读写操作比普通Buffer快,但它的创建、销毁比普通Buffer慢。
堆和栈的区别:
1、存储的东西不一样 栈存储 变量 参数值等, 堆存储 方法 对象 等
2、存储空间获取方式不同 栈是直接获取 如果空间不够直接报错,堆是先去内存链表查询节点然后分配内存然后链表节点删除
3、申请效率不容 栈是系统自动申请释放 , 堆是程序员手动释放free 如果不手动系统也会自动回收