zoukankan      html  css  js  c++  java
  • JVM(三)---堆、栈、方法区

    在这里插入图片描述

    上一篇:JVM(二)—双亲委派机制

    堆(线程共享):

      虚拟机在启动的时候创建堆,用于存放对象的实例。几乎所有的对象(包含常量池)都在堆上分配内存。当对象无法在该区分配内存的时候,将会报OutOfMemoryError,是jvm中主要的GC区域。

    堆区是jvm中进行垃圾回收的主要区域

    GC垃圾回收机制

    在这里插入图片描述
      对象实例从新生代永久代的过程就像是古代士兵打仗升级一样,那种用的不多,作用很小的对象经过不断的GC,不断地被淘汰,剩下来的升官进入老年代,最后再进入永久代

      新生代的对象相当于普通士兵,不断的上战场,不断被GC,当他升级当官了之后进入老年代可能就会指挥战斗,被GC的频率逐渐减小……

      到了永久区,就不存在GC了,绝大部分的对象在新生代就被回收了,进入老年代的对象都是极少。

      堆的内存大小并不是固定的,我们可以通过设置参数来控制堆内存的大小

      设置堆内存大小

    栈(线程私有):

      java线程执行的内存模型,一个线程对应一个栈,每个方法在执行的时候都会创建出一个栈帧用于存储局部变量表,操作数栈。动态连接,方法出口等信息。

    在这里插入图片描述
      栈是用来主管程序运行的,我们经常会听到说压栈、弹栈,在一个类中,如果有main()方法,首先会将main()方法压到栈中,然后再是其他的方法,如上图中的hello()list(),当list()方法执行完毕之后,该方法从栈里弹出去(弹栈),遵循先进后出原则。当main()方法执行完毕,程序结束。

      栈的生命周期与线程的生命周期同步,线程执行完毕,栈内存释放。

      由于栈中方法一执行结束就弹出栈,所以不存在垃圾回收

    StackOverflowError(栈溢出)?

      整个简单的代码实现一下堆栈溢出:

    public class TestController {
    
    	public static void main(String[] args) {
    		hello();
    	}
    
    	private static void hello() {
    		list();
    	}
    
    	private static void list() {
    		hello();
    	}
    }
    

    在这里插入图片描述
      知道压栈弹栈之后,分析此错误产生的原因就是list()方法和hello()方法互相循环调用,导致栈溢出:
    在这里插入图片描述

    方法区(线程共享):

      类的所有字段和方法字节码,以及一些特殊构造方法,如构造函数,接口代码也在此定义,简单说,所有定义的方法信息都存放在该区域。静态变量(static)、常量(final)、类信息(class)、运行时常量池都是在方法区中。虽然java虚拟机规范将方法区描述为一个堆的逻辑部分,但是他却有一个别名(Non-heap(非堆)),目的应该是与java堆区分开来。
    在这里插入图片描述

    常量池存放在哪里?:

      JDK1.6之前,常量池位于JVM的方法区

      JDK1.7将常量池转移到了堆中

      JDK1.8之后,永久代被取缔,取而代之的是元空间,所以此时常量池在元空间。

    下一篇:GC垃圾回收机制----GC回收算法(GC机制必会知识点)

  • 相关阅读:
    html5学习笔记
    J-Link eclipse Plug-ins install
    SEGGER J-Link install
    如何使用Redis实现分布式锁?
    在Redis里,如何从海量key中查询出某一个固定前缀所有的key?
    (必问)Redis有哪些常用数据类型?
    (必问)Http和Https的区别有哪些?
    Https的传输流程是什么?
    Cookie和Session有什么区别?
    HTTP的状态码有哪些?
  • 原文地址:https://www.cnblogs.com/wgty/p/12810443.html
Copyright © 2011-2022 走看看