【软件构造】第八章知识整理

内存管理模型:堆、栈

***对象在heap 堆中分配内存

   对象引用:指向其他对象在堆中的起始地址

   非基本数据类型的变量等价于对象引用

   每个对象可包含一组变量 ,每个变量可指向其他对象的引用

   对象引用只指向一个其他对象,而一个对象可被多个其他对象所引用。

***基于堆和栈的内存管理都是动态分配

***:存储方法调用以及方法执行中的局部数据,遵循后进先出的原则,无法支持复杂数据类型

e.g

***:自由模式的内存管理,动态分配,可管理复杂的动态数据结构

   在一块内存里分为多个小块,每块包含一个对象,或者未被占用

代码中的一个变量可以在不同时间被关联到不同的内存对象上,无法在编译阶段确定。内存对象也可以进一步指向其他对象

e.g

 

 

 

GCrootreachableunreachablelivedead

***GC:垃圾回收,识别垃圾对象,把其占用的内存加以回收

   GC的成本度量标准:执行时间 + 内存消耗+ 延迟时间 + ……

***root:包含多个方面:静态区域的数据 + 寄存器 + 目前的执行栈中的数据所指向的内存对象

***reachable:从root可达的对象

***unreachable:从root不可达的对象

***live:从root 可达的对象

***dead:从root不可达的对象

   在下图中:粉色的为live,黑色的为dead

 

 

 

GC的四种基本算法

***引用计数:在需要垃圾回收的对象上留下一个note,表明对该对象的实时参考数值,若该数值为0,则表明该对象需要被垃圾回收。即为每个object 存储一 个计数RC ,当有其他reference 指向它时,RC++ ;当其他reference 与其断开时,RC-- ;如果RC==0,则回收。

优点:简单、计算 代价分散 ,幽灵时间

缺点:不全面(容易漏掉循环引用的对象)、并发支持较弱、占用额外内存空间……

***标记-清除:为每个object设定状态位(live/dead) 并记录,即mark 阶段;将标记为dead 的对象进行清理,即sweep 可阶段。

下图中用圈表示的对象由于其状态为为白(即为dead),需要被回收清理

优点:可收集循环产生的垃圾、指针操作没有运行时间开销、对mutator松散耦合,不需要移动对象

缺点:幽灵时间长;

内存中的每个位置都必须在该算法的扫描阶段进行检查,非常消耗时间,时间复杂度为O(heap)

 

***标记-整理:

优点:解决了Mark-Sweep采集的碎片问题,可用内存放在一个大块中

      内存中对象的相对顺序保持不变

缺点:耗费许多时间收集,严重影响性能

***复制

   GC 策略与mark-compact 的区别在于:不是在同一个区域内进行整理,而是将live 对象全部复制到另一个区域。

优点:所有对象大小的分配都代价很低;

只处理live对象;

固定的空间开销;

可以收集循环产生的垃圾

简答实现合理高效的复制GC

缺点:停止和复制可能是破坏性

      需要其他简单收集器的地址空间的两倍

      复制大型对象的代价很大

      长期数据可能会被重复复制

      所有reference必须更新

      moving对象可能会破坏mutator

      广度优先复制可能会干扰局部模式

 

 

 

Java/JVM的内存管理模型:各区域、各区域的GC方法

Java GC 将堆分为不同的区域,各区域采用不同的GC 策略,以提高GC的效率

使用“-verbose:gc”在控制台或日志文件中输出JVM进行GC的全过程

***分为四个区域:EdenYounggenerationOld generationPermanentgeneration

***Young Generation:只有一小部分对象可较长时间存活,故采用copy算法减少GC;针对young generation,使用minor GC进行垃圾收集

***Old Generation:这里的对象有很高的幸存度,使用Mark-SweepMark-Compact,如果old generation 满了,则启动full GC

***perm generation 满了之后,无法存储更多的元数据,也启动full GC

 

 

 

JVM GC性能调优:参数配置、GC模式选择

***堆的大小决定着VM将会以何种频度进行GC、每次GC的时间多长,这两个指标具体取值多少为“优”,需要针对特定应用进行分析。较大的heap会导致较少发生GC,但每次GC时间很长,如果根据程序需要来设置heap大小,则需要频繁GC,但每次GC的时间较短

***通过以下参数设置young generation的尺寸:

-XX:NewSize=<n>[g|m|k]nYoung generation的大小,g/m/k代表gigabytes/megabytes/kilobytes.

-XX:MaxNewSize=<n>[g|m|k]:Young generation 的最大大小

-Xmn<n>[g|m|k]:设定Young generation的最初、最小、最大的大小

-XX:NewRatio=<n>Young generationOld generation的大小比例

-XX:SurvivorRatio=<n>Eden survivor space的大小比例

***old generation的尺寸不需要设置,根据其他各参数的取值可计算得到:

java-XX:NewSize=128m -XX:MaxNewSize=196m -Xms512m -Xmx1024m

GC模式选择

***-XX:+UseSerialGC :使用单个线程来执行所有的垃圾收集工作

***-XX:+UseParallelGC : 在young generation中并行执行次要集合,可以显著减少垃圾收集开销,但主要集合是使用单个线程执行的

***-XX:+UseConcMarkSweepGC : 收集终生代,并与执行应用程序同时执行大部分收集,在收集阶段,它会暂停一小段时间

***-XX:+UseTrainGC : 收集每一个小集合的Old generation,并尽量减少大停顿

 

 

 

Java性能调优工具:jstat, jmap, jhat, Visual VM, MAT

***jstat:获取JVM heap 使用和GC 的性能统计数据

***jmap:输出内存中的对象分布情况

   jmap -dump:导出heap dump

   jmap -heap:获得Java堆的信息

   jmap -histo:获得堆的类特定直方图

   jmap -permstat:永久代数统计

***jhat:导出heap dump,浏览/查询其中的对象分布情况;是个heap dump文件的浏览和查询工具

***jstack:获取Java线程的stack trace     

***Visual VM

   配置文件性能和内存使用

   采取并显示线程转储

   采取并浏览堆转储

   在线和离线分析核心转储

  

***MATEclipse Memory Analyzer):内存堆导出文件的分析工具

 

 

 

Java代码调优的设计模式

***singleton:某些类在应用运行期间只需要一个实例

   强制client 只能创建一个object 实例,避免因为new 操作所带来的时空性能(尤其是GC)的损失,也便于复用

  设置静态变量来存储单一实例对象,将构造器设置为private,从而client无法new,在构造器中new新实例,提供静态方法来获取单一实例对象

进一步提升性能:在需要的时候再new,而非提前构造出来

***Flyweight:该模式允许在应用中不同部分共享使objects,降低大量objects带来的时空代价

   内部特征:不管在什么场合使用该object,内部特征都不变

   外部特征:不是固定的,需要在不同场合context分别指派/计算其值

***Flyweight VS Singleton

   单例:不区分各场合下的不同表现形式,统一用一个实例表示

   轻量对象:同一个事物,具有多种不同表现形式

   Flyweightobject层面的复用比Singleton更灵活

***Prototype:通过克隆而非new来创建object

   引用拷贝:

   对象拷贝:

   浅拷贝:使用一个已知实例的成员变量对新创建实例的成员变量逐个赋值。

          只复制对象本身,但不复制对象对外的引用

           表示外泄

   深拷贝:类的拷贝方法不仅要复制对象的所有非引用成员变量值(简单数据类型),还要为引用类型(对象)的成员变量创建新的实例,并且初始化为原对象的值。

***object pool:不要扔掉object,留着后续复用

   代价:原本可被GC的对象,现在要留在pool中,导致内存浪费——用空间换时间

 

 

 

String Constant Pool字符串常量池

猜你喜欢

转载自blog.csdn.net/qq_41772794/article/details/80783153
今日推荐