首页 技术 正文
技术 2022年11月9日
0 收藏 998 点赞 3,724 浏览 3772 个字

Java内存区域和GC机制
一、目录
1.Java垃圾回收概括
2.Java内存区域
3.Java对象的访问方式
4.Java内存访问机制
5.Java GC 机制
6.Java垃圾收集器

二、Java垃圾回收概括
1.Java GC 介绍:
  a)Garbage Collection 垃圾收集、垃圾回收机制;
  b)Java中不需要编写内存回收和垃圾清理代码,也不需要考虑内存泄漏和溢出的问题;
  c)因为在Java虚拟机中存在自动内存管理和垃圾清理机制;
  d)该机制会对JVM(Java 虚拟机)中的内存进行标记,并确定哪些内存需要回收,根据回收策略,自动的回收内存,永不停息的保证JVM中的内存空间,防止出现内存泄漏和溢出问题;
  e)说明:关于JVM(Java虚拟机)是指HotSpot虚拟机

2.Java GC 主要做以下三件事:
  a)确定哪些内存需要回收
  b)确定什么时刻执行垃圾回收机制
  c)如何执行垃圾回收机制

三、Java GC机制学习
1.学习方向有以下四个:
  a)内存是如何分配的;
  b)如何保证内存不被错误回收(即哪些内存需要被回收);
  c)在什么情况下执行GC以及执行GC的方式;
  d)如何监控和优化GC机制

2.Java内存区域(Java运行时内存划分)
  a)程序计数器(program counter register)
    1.程序计数器是一个较小的内存区域;
    2.用于指示当前线程所有执行的字节码执行到了第几行;
    3.每个程序计数器只用来记录一个线程的行号,所以他是”线程私有”
    4.注:
      I )如果程序执行的是一个Java方法,则计数器记录的是正在执行的虚拟机字节码指令地址;
      II)如果正在执行的是一个本地方法,则计数器的值为undefined;
      III) 由于程序计数器只是记录当前指令地址,所以不存在内存溢出,所以,程序计数器是JVM内存区域中唯一一个没有定义outofmemoryerror的区域;

  b)虚拟机栈(JVM stack)
    1.一个线程的每个方法在执行的同时,都会创建一个栈帧;
    2.栈帧中存储的有局部变量表、操作站、动态链接、方法出口等;
    3.当方法被调用时,栈帧在JVM栈中入栈,当方法执行完之后,栈帧出栈;
    4.虚拟机栈中定义了两种异常:
      I )栈溢出:如果线程调用的栈深度大于虚拟机允许的最大深度,则抛出StatckOverFlowError;
      II)内存溢出:由于大多数Java虚拟机都能允许动态扩张虚拟机栈的大小,所以线程可以一直申请栈,直到内存不足而抛出OutOfMemoryError;
    5.每个线程对应着一个虚拟机栈,因此虚拟机栈也是线程私有的;

  c)本地方法栈
    1.本地方法栈在”作用”、”运行机制”、”异常类型”等方面都与”虚拟主机栈”相同;
    2.唯一的区别是:虚拟主机栈是执行Java方法的,而本地方法栈是用来执行本地(native)方法的;

  d)堆区
    1.在JVM所管理的内存中,堆区是最大的一块;
    2.堆区也是Java GC机制所管理的主要内存区域;
    3.堆区由所有线程共享,在虚拟机启动时创建;
    4.堆区的存在是为了存储”对象实例”;
    5.所有的对象都在堆区上分配内存(也有在”栈”上分配内存的)
    6.堆区的大小是可以动态扩展的;
    7.如果在执行垃圾回收之后,仍没有足够的内存分配,也不能再扩展,将会抛出OutOfMemoryError:Java heap sapce异常;

  e)方法区
    1.在Java虚拟机规范中,将”方法区”作为一个逻辑部分来对待,但”方法区”并不是”堆”;
    2.方法区在物理上也不需要连续的,可以选择固定大小或可扩展大小;
    3.可以选择是否执行垃圾收集;但方法区上执行垃圾收集很少,这就是为什么称方法区为”永久代”的原因;
    4.方法区上面的”””垃圾收集”””主要是针对常亮”””常量池”””的内存回收和对已加载类的卸载;
    5.在方法区上执行垃圾收集很困难,所以不考虑;
    6.在方法区上定义了OutofMemoryError:PermGen space异常,在内存不足时抛出异常;
    7.运行池常量:
      I )用于存储编译期常量(编译时就产生的字面常量、符号引用)
      II)还可以存储”””运行时间内”””产生的常量,目的是为了维护一个常量池,如果调用的字符串”abc”已经在常量池中,则返回池中的字符串地址;否则新建一个常量加入常量池中,并返回地址;

  f)直接内存
    1.直接内存并不是JVM管理的内存,它是JVM以外的机器内存;
    2.比如物理内存是4G,JVM占用了1G,则剩下的3G就是直接内存;
    3.由于直接内存受到本机器内存的限制,也有可能出现OutOfMemoryError的异常;

四、Java对象的访问方式
一个Java的引用访问涉及到3个内存区域:JVM栈、堆、方法区
  1.通过句柄访问
  2.通过直接指针访问
    a)reference中存储的就是对象在堆中的实际地址,在堆中存储的对象信息中包含了在方法区中的相应类型数据。这种方法最大的优势是速度快,在HotSpot虚拟机中用的就是这种方式。

五、内存分配机制
  1.这里所说的内存分配是指在”””堆”””上的分配,一般的,对象的内存分配都是在堆上进行;
  2.Java内存分配和回收的机制概括的说就是:
    a)分代分配
    b)分代回收
  3.对象根据存活的时间被分为:
    a)年轻时代
    b)年老时代
    c)永久时代(也就是方法区)

  4.年轻时代:
    a)对象被创建时,内存的分配首先发生在年轻时代(大数据可以直接创建在年老代);
    b)大部分的对象在创建后很快就不能再使用,于是被年轻的GC机制清理掉;
    c)年轻代上的内存分配:
      1.Eden 内存首次分配区
      2.survivor0/1 两个存活区
      3.绝大多数刚创建的对象会被分配在Eden区,其中的大多数对象很快就会消亡。Eden区是连续的内存空间,因此在其上分配内存极快;
      4.当Eden区满的时候,执行Minor GC,将消亡的对象清理掉,并将剩余的对象复制到一个存活区Survivor0(此时,Survivor1是空白的,两个Survivor总有一个是空白的);
      5.此后,每次Eden区满了,就执行一次Minor GC,并将剩余的对象都添加到Survivor0;
      6.当Survivor0也满的时候,将其中仍然活着的对象直接复制到Survivor1,以后Eden区执行Minor GC后,就将剩余的对象添加Survivor1(此时,Survivor0是空白的);
      7.当两个存活区切换了几次(HotSpot虚拟机默认15次,用-XX:MaxTenuringThreshold控制,大于该值进入老年代)之后,仍然存活的对象(其实只有一小部分,比如,我们自己定义的对象),将被复制到老年代。

    d)从上面的过程可以看出,Eden区是连续的空间,且Survivor总有一个为空;
    e)经过一次GC和复制,一个Survivor中保存着当前还活 着的对象,而Eden区和另一个Survivor区的内容都不再需要了,可以直接清空,到下一次GC时,两个Survivor的角色再互换。
    f)因此,这种方式分配内存和清理内存的效率都极高,这种垃圾回收的方式就是著名的“停止-复制(Stop-and-copy)”清理法(将Eden区和一个Survivor中仍然存活的对象拷贝到另一个Survivor中)
    g)使用了两种技术加快内存分配:
      1.这两种技术分别是bump-the-pointer和TLAB;
      2.对于bump-the-pointer:
      由于Eden区是连续的,因此bump-the-pointer技术的核心就是跟踪最后创建的一个对象,在对 象创建时,只需要检查最后一个对象后面是否有足够的内存即可,从而大大加快内存分配速度;

  3.对于TLAB:
    TLAB技术是对于多线程而言的,将Eden区分为若干 段,每个线程使用独立的一段,避免相互影响。TLAB结合bump-the-pointer技术,将保证每个线程都使用Eden区的一段,并快速的分配内存;

  4.年老代:
    a)对象如果在年轻代存活了足够长的时间而没有被清理掉,则会被复制到老年代;
    b)老年代的特点是空间更大,可以存放更多对象,发生GC的次数更少;
    c)当年老代内存不足时,执行Full GC;
    d)可以采用动态控制策略,动态调整Java堆中各个区域的大小以及进入年老代的年龄;
    e)如果对象比较大,且年轻代空间不足,则大对象会被直接分配到老年代上(但是大对象容易触发GC,应该少用);

六、每个分代的收集方法(GC机制的基本算法是:分代收集)
1.年轻代
2.老年代
3.方法区(永久代)

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,494
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,908
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,740
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,495
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,133
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,297