Java内存分析

Posted Code_BinBin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java内存分析相关的知识,希望对你有一定的参考价值。

Java内存分析

Java内存

  • 存放new的对象和数组
  • 可以被所有线程共享,不会存放别的对象引用
  • 继续细分:
    • 新生代
      • 伊甸园区(所有对象在这里创建)
      • 幸存区(两个)
    • 老年代(存储常量池和一些经过多次GC后仍然存活的对象)
    • 元空间(持久代(非堆),只是逻辑上属于堆中,实际上不一定)
      • 方法区
      • 一些java运行的环境与配置jar包

  • 存放基本变量类型(包含具体数值)
  • 引用对象的变量(存放对象地址,用于找到堆内变量的具体地址)
  • 线程不会共享

方法区

  • 方法区在元空间中
  • 可以被所有线程共享
  • 包含了类所对应的唯一字节码对象,和其中的静态变量,常数

本地方法区

  • 存储用native修饰后的本地方法
  • 因为java运行在jvm上,无法直接操控计算机硬件
  • 可以通过native修饰的本地方法,调用JVM底层的c++代码,对计算机硬件进行控制

类加载的过程

GC垃圾回收

算法

引用计数法

  • 思想:每一个对象都有一个counter,只要有任何一个对象引用了该对象,则其counter加1,当引用失效时,counter减1,当counter为0时,对象不存在任何引用,在GC时被清除

  • GC过程:counter在每次引用生效和失效时进行加减法操作,并判断是否为0,是则清除

  • 优点:只需要为每一个对象配备一个整型的计数器

  • 缺点

    1. 无法处理循环引用问题,可能会造成死锁:如对象A和对象B互相引用,但不存在其他对象引用A和B,此时A和B属于不可达的对象,即垃圾对象,但是counter无法识别此类垃圾对象间的互相引用,从而引起内存泄露,不能GC
    2. 计数器一样存在资源的消耗

标记清除法

  • 思想:标记所有的可达对象(存在引用的对象),则未被标记的对象就是不存在引用的垃圾对象,GC时清除所有未被标记的对象
  • GC过程:标记清除法的GC时经历标记 + 清除两个过程,先标记,后清除
  • 优点:只存在循环引用不存在其他引用的对象不会被标记,解决了循环引用问题
  • 缺点:可能会产生内存碎片(不连续的内存空间),不连续的内存空间在内存分配时的工作效率低于连续的内存空间,尤其是对大对象的的内存分配

标记压缩法

  • 思想标记压缩法是对标记清除法的优化,所以也叫标记清除压缩法。和标记清除法一样,先标记所有的可达对象(存在引用的对象),不同的是,标记完成后并不是直接清除未标记的垃圾对象,而是将所有的被标记的对象(即存活对象)压缩到内存空间的一端后在清理边界外所有的空间。

  • GC过程:分为标记+压缩+清除 三个步骤

  • 优点:解决了标记清除法带来的空间碎片问题,又不需要折损可使用空间(复制算法折损了可使用空间)

复制算法

  • 思想:将内存空间分为两块相同的存储空间,每次只使用一块,GC时,将正在使用的内存中的存活对象复制到另一块存储空间中,然后清除正在使用的空间的所有对象

  • GC过程:先复制,再清除

  • 优点:存活对象相对少时,效率很高(因为需要复制的对象少),存活对象复制到另一空间时,解决了空间碎片问题,保证了内存空间的连续性,又避免了大量的空间浪费

  • 缺点:系统内存只能使用一半的内存空间,而且如果存活对象相对多的话,比较耗时

  • 应用场景:java新生代串行垃圾回收器

    新生代分为eden空间、from空间和to空间3个部分,其中from和to空间是两块相同的空间,同一时间只使用其中一块空间,另一空间用于GC时存放复制的存活对象,from和to空间也称为survivor空间,用于存放未被回收的对象。

分代算法

  • 思想:将内存空间根据对象的特点不同进行划分,选择合适的垃圾回收算法,以提高垃圾回收的效率。
  • GC过程:因为不同的对象使用的算法不一致,所以GC的过程也不一样,例如,新生代使用复制算法,老年代使用标记压缩法
  • 优点:提高了垃圾回收的效率
  • 应用场景:分代的思想被现有的虚拟机广泛使用,几乎所有的垃圾回收器都区分新生代和老年代。

作者:姜小姜小
链接:https://www.jianshu.com/p/4bdc443f5c92
来源:简书

JVM调优参数

一、堆设置

  • -Xms:初始堆大小

  • -Xmx:最大堆大小

  • -XX:NewSize=n:设置年轻代大小

  • -XX:NewRatio=n:设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4

  • -XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5

  • -XX:MaxPermSize=n:设置持久代大小

  • 注:以Tomcat服务启动,对于参数设置,在tomcat的bin目录下,window系统在catalina.bat中设置,Linux系统在catalina.sh中设置

    jvm01 jvm02

二、收集器设置

  • -XX:+UseSerialGC:设置串行收集器
  • -XX:+UseParallelGC:设置并行收集器
  • -XX:+UseParalledlOldGC:设置并行年老代收集器
  • -XX:+UseConcMarkSweepGC:设置并发收集器

三、垃圾回收统计信息

  • -XX:+PrintGC
  • -XX:+PrintGCDetails
  • -XX:+PrintGCTimeStamps
  • -Xloggc:filename

四、并行收集器设置

  • -XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数。并行收集线程数。
  • -XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间
  • -XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)

五、并发收集器设置

  • -XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。

  • -XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。

  • 注:在eclipse中设置JVM启动参数,在Run菜单下的“run configurations”配置:

    jvm03

原文链接:https://blog.csdn.net/Apeopl/article/details/82701684

以上是关于Java内存分析的主要内容,如果未能解决你的问题,请参考以下文章

内存泄露分析

使用MAT分析Java内存

#yyds干货盘点# Java 内存分析之堆内存和MetaSpace内存

Android常见内存泄露分析及MAT与Profiler内存分析时间

java执行程序的内存分析系列专栏二之static变量和方法内存分析

java内存模型分析2