内存模型和结构
堆:线程共享。所有对象实例以及数组都要在堆上分配。回收期主要管理对象。
堆的作用是存放对象实例和数组。从结构上来分,可以分为新生代和老年代。而新生代又可以分为eden空间 、From Survivor空间、To Survivor空间。所有新生成的对象首先都是放在新生代的。需要注意,Survivor的两个去是对称的,没先后关系,所以同一个区中可能同时存在从Eden赋值过来的对象,和从一个survivor赋值过来的对象,而赋值到老年代的只有从第一个survivor区过来的对象。而且,survivor区总有一个是空的。 控制参数 -Xms 设置堆的最小空间大小。-Xmx设置堆的最大空间大小。-XX:NewSize设置新生代最小空间大小。-XX:MaxNewSize设置新生代最小空间大小 垃圾回收 此区域是垃圾回收的主要操作区域。 异常情况 如果堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OOM
方法区:线程共享。存储类信息、常量、静态变量、即时编译器后的代码
方法区和java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫non-heap,目的应该是java堆区分开来。 很多人愿意把方法区称为永久代(jdk1.8 元空间),本质上两者并不等价,仅仅是因为虚拟机的设计团队选择把GC分代手机扩展到方法区,或者说使用永久代来实现方法区而已。 控制参数 -XX:PermSize 设置最小空间 -XX:MaxPermSize 设置最大空间 垃圾回收 对此区域会涉及但是很少进行垃圾回收。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载,一般类说着个区域的回收成绩比较难以令人满意 异常情况 根据java虚拟机规范的规定,当方法区无法满足内存分配需求时,抛出OOM
方法栈:线程私有。存储局部变量表、操作栈、动态链接、方法出口、对象指针
每个线程会有一个私有栈。每个线程中方法的调用又会在本栈中创建一个栈帧。在方法栈中会存放编译期可知的基本数据类型、对象引用类型。 控制参数 -Xss 控制每个线程栈的大小 异常情况 在java虚拟机规范中,对这个区域规定了两种异常状况 StackOverFlowError:异常线程请求的栈深度大洋芋虚拟机所允许的深度时抛出 OutOfMemoryError:虚拟机栈可以动态扩展,当扩展时无法申请到足够的内存时会抛出。
本地方法栈:线程私有。为虚拟机使用native方法服务。如java使用c或c++编写的接口服务时,代码在此区运行。
本地方法栈与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行java方法服务,而本地方法栈则是为虚拟机使用到的native方法服务 控制参数 -Xss 控制每个线程大小 异常情况 与虚拟机栈一样,本地方法栈区域也会抛出栈溢出、内存溢出
程序计数器:线程私有。当前线程所执行的字节码的行号指示器,指向下一条执行的指令