堆 栈 方法区 区别和使用

4、java堆

主要用于分配对象实例和数组。

5、方法区

线程共享

用于存储已被虚拟机加载的类信息、常量、静态变量、即使编译后的代码等数据

6、直接内存

直接内存并不是虚拟机运行时数据区的一部分。在NIO中,引入了一种基于通道和缓冲区的I/O方式,它可以使用native函数直接分配堆外内存,然后通过一个存储在java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。

7、栈

主要存放 动态链接方法、返回值、返回地址等信息

 

堆溢出

堆溢出原因莫过于对象太多导致。

2、栈溢出

根据JAVA虚拟机规范描述:

如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError

扫描二维码关注公众号,回复: 2979141 查看本文章

如果虚拟机在扩展栈时无法申请到足够的内存空间,将抛出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 如果不手动系统也会自动回收

猜你喜欢

转载自blog.csdn.net/u010310183/article/details/81947223