• jvm内存分区


    1、方法区 

    (1)主要用来存储已被虚拟机加载的类的信息、常量、静态变量和即时编译器编译后的代码(JIT)等数据

    (2)有时候也称为永久代,在该区内很少发生垃圾回收,但是并不代表不发生GC,在这里进行的GC主要是对方法区里的常量池和对类型的卸载

    (3)是各个线程共享的区域

    (4)方法区里有一个运行时常量池,用于存放静态编译产生的字面量和符号引用。该常量池具有动态性,也就是说常量并不一定是编译时确定,运行时生成的常量也会存在这个常量

    2、虚拟机栈

    (1)虚拟机栈也就是我们平常所称的栈内存,它为 java 方法服务,每个方法在执行的时候都会创建一个栈帧,用于存储局部变量表(基本数据类型、returnAddress类型和对象引用,通过索引访问)、操作数栈(存储运算结果以及运算的操作数,通过压栈和出栈的方式访问)、动态链接和方法出口等信息

    (2)线程私有的,它的生命周期与线程相同

    (3)异常:

    StackOverflowError:线程请求的深度大于虚拟机栈的深度

    OutOfMemoryError:扩展时无法申请到足够的内存

    3、本地方法栈
    本地方法栈和虚拟机栈类似,只不过本地方法栈为Native方法服务。

    4、堆

    JVM的堆是运行时数据区,所有类的实例和数组都是在堆上分配内存。它在JVM启动的时候被创建。对象所占的堆内存是由自动内存管理系统也就是垃圾收集器回收。
    堆内存是由存活和死亡的对象组成的。存活的对象是应用可以访问的,不会被垃圾回收。死亡的对象是应用不可访问尚且还没有被垃圾收集器回收掉的对象。一直到垃圾收集器把这些对象回收掉之前,他们会一直占据堆内存空间。

    (1)对于大多数应用来说,java堆是java虚拟机所管理的内存中的最大的一块

    (2)java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建

    (3)此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例对在这里分配内存

    (4)如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,OutOfMemoryError异常

    (5)是垃圾收集器管理的主要区域

    (6)堆里面的分区

    堆里面分为新生代(Eden+Survivor区(分为from和to区))和老生代(java8取消了永久代,采用了Metaspace),内存回收时,如果用的是复制算法,从from区复制到to区,当经过一次或者多次GC之后,存活下来的对象会被移动到老年区,当JVM内存不够用的时候,会触发Full GC,清理JVM老年区。当新生区满了之后会触发YGC(新生代内存不够用时候发生 MGC 也叫 YGC,JVM 内存不够的时候发生 FGC),先把存活的对象放到其中一个Survice区,然后进行垃圾清理。因为如果仅仅清理需要删除的对象,这样会导致内存碎片,因此一般会把Eden进行完全的清理,然后整理内存。那么下次GC的时候,就会使用下一个Survive,这样循环使用。如果有特别大的对象,新生代放不下,就会使用老年代的担保,直接放到老年代里面。因为JVM认为,一般大对象的存活时间一般比较久远(可以避免在Eden区及两个Survivor区之间发生大量的内存分配)

    5、程序计数器

    (1)一块较小的内存空间,它的作用是当前线程所执行的字节码行号指示器,唯一一个在jvm中没有规定任何OutOfMemoryError的区域

    (2)一个处理器只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器(线程私有)



    6、举例

    String str = new String(“hello”);

    str:栈

    new出来的对象放在堆

    hello存储在静态存储区(主要存放静态数据、全局数据和常量)

  • 相关阅读:
    网络爬虫的基本原理(一)
    灵光一闪-软件应用
    sql语句变量定义和样例
    windows+linux环境部署搭建
    jdk1.6安装
    系统部署
    tomcat部署
    maven各种插件在总结
    maven项目tomcat部署问题
    两种数据源
  • 原文地址:https://www.cnblogs.com/zhai1997/p/12687713.html
Copyright © 2020-2023  润新知