java中JVM内存管理(1)

Java岗位面试,JVM是对程序员基本功考察,一般会问你对JVM了解吗?  能够分几部分回答这个问题,首先JVM内存划分 | JVM垃圾回收的含义  |  有哪些GC算法  以及年轻代和老年代各自特色等等程序员

 1) JVM内存划分:面试

    ①  方法区 (线程共享)  常量  静态变量  JIT(即时编译器)编译后代码也在方法区存放算法

    ② 堆内存(线程共享) 垃圾回收的主要场地bootstrap

    ③  程序计数器  当前线程执行的字节码的位置指示器缓存

    ④   Java虚拟机栈(栈内存) :保存局部变量,基本数据类型以及堆内存中对象的引用变量服务器

    ⑤ 本地方法栈  (C栈):为JVM提供使用native方法的服务多线程

经过这幅图了解一下性能

         

  JDK 1.8同JDK 1.7 ,最大的区别是:元数据取代了永久代.元空间的本质和永久代相似,都是对JVM规范中的方法区的实现.其元空间和永久代之间的最大区别在于:元数据空间不在虚拟机中,而是在本地内存中spa

详细了解一下各个部分线程

   01)程序计数器(PC寄存器)

    程序计数器的定义:程序计数器是一块较小的内存空间,是当前线程正在执行的哪一条字节码指令的地址,若当前线程正在执行的是一个本地方法,那么此时程序计数器为Undefined

    程序计数器的做用:

    • 字节码解释器经过改变程序计数器来依次获取指令,从而实现代码的流程的控制
    • 在在多线程状况下,程序计数器记录的是当前线程执行的执行的位置,从而当线程切换回来时,就知道上次线程执行到哪了

    程序计数器的特色

    • 是一块较小的内存空间
    • 线程私有,每一个线程都有本身的程序计数器
    • 生命周期:随着线程的建立而建立,随着线程的销毁而销毁
    • 是一个惟一不会出现的OutOfMemoryError的内存区域

  02)Java虚拟机栈

    定义:描述Java方法运行过程的内存模型

    Java虚拟机栈会为每个即将运行的Java方法建立一块叫作"栈帧"的区域,用于存放该方法运行过程当中的一些信息,如  局部变量表  /操做数栈  /动态连接 /方法出口信息  .............

    

    压栈出栈过程:

    当方法运行过程当中须要建立局部变量时,就将局部变量的值存入栈帧的局部变量表中

    Java虚拟机栈的栈顶是当前正在执行的活动栈,也就是当前正在执行的方法,PC寄存器也会指向这个地址,只有这个活动的栈帧的本地变量能够被操做数栈操做,当前这个栈帧中调用另外一个方法,与之对应的额栈帧又会被建立,新建立的栈帧压入栈顶,变成当前的活动栈帧,方法结束后,当前栈帧的返回值变成新的活动栈帧的中的操做数栈的一个操做数,若是没有返回值,那么新的活动栈帧中操做数栈的操做数没有变化

    因为Java虚拟机栈是线程对应的,数据不是共享的,所以不用关心数据一致性问题,也不会存在同步锁的问题

    特色

    • 局部变量表随着栈帧的建立而建立,他的大小在编译时肯定,建立时只需分配事先规定的大小便可,在方法运行的过程当中,局部变化表的大小不会发生变化
    • Java虚拟机栈会出现两种异常:StackOverFlowError和OutOfMemoryError
    • StackOverFlowError若Java虚拟机栈的大小不容许动态扩展,那么当前线程请求的栈的深度超过当前的Java虚拟机栈的最大深度是,就会抛出此异常
    • OutOFMemoryError,若容许动态扩展,那么当前线程的请求的栈内存用完了,没法再动态扩展时,抛出此异常
    • Java虚拟机栈也是线程私有,随着线程建立而建立,随着线程的结束而销毁

  03)本地方法栈(C栈)

    定义:是为了JVM运行native方法准备的空间,因为不少native方法都是用C语言实现的,因此一般又叫C栈,它与Java虚拟机栈实现的功能相似,只不过本地方法栈描述本地方法运行过程的内存模型

    栈帧变化过程:

    本地方法被执行时,在本地方法栈也会建立一块栈帧,用于存放该方法的局部变量表  /操做数栈 /动态连接 /方法出口等信息; 方法结束后,相应的栈帧也会出栈,并释放内存空间.也会抛出StackOverFlowError和OutOfMemoryError异常

  04) 堆

    定义:堆是用来对象的内存空间,几乎全部的对象都存储在堆中

    特色:

    • 线程共享,整个Java虚拟机只有一个堆,全部线程都访问同一个堆.
    • 在虚拟机启动时建立
    • 是垃圾回收的主要场地
    • 进一步可分为:新生代(Eden区 From Survior To Surviror)  老年代

    不一样的区域存放的不一样生命周期的对象,这样能够根据不一样区域使用不一样的垃圾回收算法,更具备针对性. 堆的大小也能够固定也能够扩展,对于主流的虚拟机,堆大小可扩展的,所以当线程请求分配的内存,但堆已满,且内存已没法再扩展,就抛出OutOfMemoryError异常

  05)方法区

    定义:Java虚拟机规范中定义方法区是堆的一个逻辑部分,方法区存放如下信息  已被虚拟机加载的类信息  /常量  /静态变量 /即时编译后代码

    特色:

    • 线程共享.方法区是堆的一个逻辑部分,所以和堆同样,都是线程共享,整个虚拟机中只有一个方法区
    • 永久代 方法区中的信息通常须要长期存在,并且它又是堆的逻辑分区,所以用堆的划分方法,把方法区称为"永久代"
    • 内存回收的效率低.方法区中的信息通常须要长期存在,回收一遍只有少许信息无效.主要回收的目标是: 对常量池的回收;对类型的卸载
    • Java虚拟机规范l对方法区的要求比较宽松,和堆同样,容许固定大小.也容许动态扩展,还容许不实现垃圾回收

    运行时常量池:

      方法区中存放:类信息  常量  静态变量  即时编译器变编译后代码.常量就存放在运行时常量池中.当类被Java虚拟机加载后,.class文件中的常量就存在方法区的运行常量池,并且在运行期间,能够向常量池中添加新的常量,如String类的intern()方法就能在运行期间向常量池中添加字符串常量

  06) 直接内存(堆外内存)

  直接内存是除Java虚拟机以外的内存,但有可能被Java使用

  操做直接内存:

    在NIO中引入了一种基于通道和缓存的IO方式,他能够调用本地方法的直接分配Java虚拟机以外的内存,而后经过一个存储在堆中的DirectByteBuffer对象直接操做该内存,而无需将外部内存中数据复制到堆中再进行操做,从而提升数据操做的效率,直接内存的大小不受Java虚拟机,也会抛出OutOfMemoryError异常

  直接内存和堆内存比较

  • 直接内存申请空间耗费更高的性能
  • 直接内存读取IO的性能优于普通的堆内存
  • 直接内存的做用链:本地IO-->直接内存-->本地IO
  • 堆内存的做用链:本地IO-->直接内存-->非直接内存-->直接内存--->本地IO
服务器管理员在配置虚拟机参数时,会根据实际内存设置  -Xmx等参数信息,但常常忽略直接内存,使得各个
内存区域总和大于物理内存,从而致使动态扩展时出现OutOFMemoryError

 

 2)相似 -Xms  -Xmn这些参数的含义

   堆内存分配

    ① : JVM初始分配的内存由-Xms指定,默认是物理内存的1/64

    ②:  JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4

    ③: 默认空余堆内存小于40%时,JVM就会增长堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减小堆直到-Xms的最小限制

    ④: 所以服务器通常设置-Xms  -Xmx相等以免在每次GC后调整堆大小. 对象的堆内存由成为垃圾回收器的自动内存管理系统回收

   非堆内存分配:

    ①:JVM使用-XX:PermSize 设置非堆内存的初始值,默认物理内存的1/64;

    ② :由XX:MaxPermSize设置设置最大非堆内存的大小

    ③: -Xmn2G :设置年轻代的大小为2G

    ④ :-XX:SurvivorRatio ,设置年轻代中Eden区与Survivor区的比值

 3)垃圾回收的算法有哪些?

    ① 引用计数法:原理是在此对象有个引用,即增长一个计数,删除一个引用则减小一个计数.垃圾回收时,只收集计数为0的对象.此算法的最致命的没法处理循环引用的问题

    ②: 标记-清除 :此算法分两个阶段,第一阶段从引用的根节点开始标记全部被引用的对象,第二阶段遍历整个堆,把未标记的对象清除,此算法须要暂停应用,同时产生内存碎片

    ③: 复制算法 此算法把内存划分为两个相等的区域,每次只使用一个区域,垃圾回收时,遍历当前使用的区域,把正在使用的对象复制到另外一个区域中每次算法每次只处理正在使用的对象,所以复制的成本比较小,同时复制过去之后还能进行相应的内存整理,不会出现"碎片问题",此算法的缺点也很明显,须要两倍的内存空间

    ④: 标记-整理:此算法结合了"标记-清除"和:复制算法的两个的优势,也是分两个阶段,第一个阶段从根节点开始标记全部被引用对象,第二阶段遍历整个堆,清除未标记的对象而且把存活的对象"压缩"到堆的其中一块,按顺序排放,,此算法避免"标记-清除"的碎片问题,同时也避免"复制"的空间问题

 4)root搜索算法中,哪些能够做为root?

  • 被启动类(bootstrap加载器)加载的类和建立的对象
  • JavaStack中引用的对象(栈内存中引用的对象)
  • 方法区中静态引用
相关文章
相关标签/搜索