我爱编程计算机微刊轮子工厂

Java内存模型及GC原理

2018-07-10  本文已影响2人  在北方玩弹子球

Java内存模型

堆是Java代码可及的内存,留给开发人员使用的;非堆是JVM留给自己用的,包含方法区、JVM内部处理或优化所需的内存(如 JIT Compiler,Just-in-time Compiler,即时编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码。

  1. 堆内存(Heap Memory): 存放Java对象
  2. 非堆内存(Non-Heap Memory): 存放类加载信息和其它meta-data
  3. 其它(Other): 存放JVM 自身代码等
image

Java内存分配

image
  1. JVM 会试图为相关Java对象在Eden中初始化一块内存区域
  2. 当Eden空间足够时,内存申请结束;否则到下一步
  3. JVM 试图释放在Eden中所有不活跃的对象(这属于1或更高级的垃圾回收),释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区
  4. Survivor区被用来作为Eden及OLD的中间交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会被保留在Survivor区
  5. 当OLD区空间不够时,JVM 会在OLD区进行完全的垃圾收集(0级)
  6. 完全垃圾收集后,若Survivor及OLD区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现”out of memory”错误

GC基本原理

编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显式操作方法。所以,Java的内存管理实际上就是对象的管理,其中包括对象的分配和释放。

GC分代划分

详解函数finalize

   protected void finalize() throws Throwable { }

  1. 其一、GC为了能够支持finalize函数,要对覆盖这个函数的对象作很多附加的工作。
  2. 其二、在finalize运行完成之后,该对象可能变成可达的,GC还要再检查一次该对象是否是可达的。因此,使用 finalize会降低GC的运行性能。
  3. 其三、由于GC调用finalize的时间是不确定的,因此通过这种方式释放资源也是不确定的。

GC程序交互

// 申请一个图像对象  
         Image image=new Image();       // 创建Image对象  
         …  
         // 使用 image  
         …  
         // 使用完了image,将它设置为soft 引用类型,并且释放强引用;  
         SoftReference sr=new SoftReference(image);  
         image=null;  
         …  
         // 下次使用时  
         if (sr!=null)   
  image=sr.get();  
         else{  
  //由于GC由于低内存,已释放image,因此需要重新装载;  
                image=new Image();  //由于GC由于低内存,已释放image,因此需要重新装载;  
                sr=new SoftReference(image);  
         }

Java编程建议

  1. 最基本的建议就是尽早释放无用对象的引用。大多数程序员在使用临时变量的时候,都是让引用变量在退出活动域(scope)后,自动设置为 null.我们在使用这种方式时候,必须特别注意一些复杂的对象图,例如数组,队列,树,图等,这些对象之间有相互引用关系较为复杂。对于这类对象,GC 回收它们一般效率较低。如果程序允许,尽早将不用的引用对象赋为null,这样可以加速GC的工作。
  2. 尽量少用finalize函数。finalize函数是Java提供给程序员一个释放对象或资源的机会。但是,它会加大GC的工作量,因此尽量少采用finalize方式回收资源。
  3. 如果需要使用经常使用的图片,可以使用soft应用类型。它可以尽可能将图片保存在内存中,供程序调用,而不引起OutOfMemory.
  4. 注意集合数据类型,包括数组,树,图,链表等数据结构,这些数据结构对GC来说,回收更为复杂。另外,注意一些全局的变量,以及一些静态变量。这些变量往往容易引起悬挂对象(dangling reference),造成内存浪费。
  5. 当程序有一定的等待时间,程序员可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。使用增量式GC可以缩短Java程序的暂停时间。

在我的与专栏同名公众号【轮子工厂】后台回复关键字:
1.回复【图书】:获取15本新手自学编程,零基础入门经典学习教材;
2.回复【我要造轮子】:获取100多本我根据知乎上面关于计算机问题的高赞回答里面的介绍整理出来的书籍;
3.回复【开发工具】:获取几大主流编程语言的开发工具~
4.回复【ps教程】:获取ps视频免费教程;

上一篇 下一篇

猜你喜欢

热点阅读