四、本地方法栈
本地方法栈的作用与虚拟机栈类似,只不过虚拟机栈是为Java方法服务的,而本地方法栈是为本地方法服务的。在Hotspot中,将本地方法栈和虚拟机栈合二为一。与虚拟机一样,本地方法栈同样会在线程请求的虚拟机栈深度超过虚拟机所允许的深度和栈扩展内存不足时,分别抛出StackOverflowError和OutOfMemoryError异常
五、堆
对于大多数Java程序,Java堆是虚拟机所管理的最大的一块内存空间,Java堆是所有线程共享的一块区域,在虚拟机启动时创建,所有的类实例和数组都储存在这块区域,这个区域也是垃圾收集器主要收集的区域
《Java虚拟机规范》中规定,Java堆可以被实现为固定大小,也可以是可扩展的,目前主流的虚拟机都可以通过参数-Xmx和-Xms来设置堆的最大和最小大小。Java堆可以是物理上不连续的内存空间,但逻辑上应该是连续的。当Java堆没有足够的内存分配对象空间,并且无法再扩展时,会抛出OutOfMemoryError异常。
六、方法区
方法区和堆一样,都是所有线程共享的内存区域,用来储存类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。虽然方法区在逻辑上是堆的一部分,但简单实现可以不实现垃圾收集。和Java堆一样,方法区不需要连续的物理内存,也可以被实现为固定大小和可扩展的。 这块区域的垃圾回收主要是针对常量池的回收和堆类型的卸载,一般来说回收效果都不会太好,但这块区域的回收有时候是必要的。根据《Java虚拟机规范》的规定,当方法区没有足够的内存满足新的内存分配需求时,将抛出OutOfMemoryError异常。
七、运行时常量池
运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池表,用于存放编译期生成的各种字面量和符号引用,这部分内容在类加载后存放到运行时常量池。因为常量并不一定只在编译时产生的,运行时同样也能产生新的常量,所以运行时常量池允许在运行时动态地将常量放入常量池,如String::intern。
由于运行时常量池是方法区的一部分,当常量池没有足够的内存满足内存分配需求时,同样会抛出OutOfMemoryError异常。