Java语言中 的垃圾收集器相对于以前的其他语言优势是什么?

  过去的语言需要程序员显示的进行分配内存、释放内存。这种做法可能会引起“内存泄漏”,即由于某种原因是分配给程序的内存无法释放,如果该任务不断的重复进行,程序的内存将会耗尽而导致程序异常终止,甚至无法继续工作,相比之下:Java语言不要求程序员显示的调用内存分配和释放内存,避免了很多潜在的问题。Java在创建对象的时候会自动的分配内存,并当对象的引用不存在的时候释放这块内存。

  Java中使用被称为垃圾收集器的技术来监视Java程序的运行,当对象不再使用的时候就自动释放对象所使用的内存,一般情况下无需显示的请求垃圾收集器,程序运行时垃圾收集器会不定时的检查对象的各个引用。

注意:GC即是垃圾收集机制,是指JVM用于释放那些不再使用的对象的内存,Java语言并不要求JVM有GC,也没有规定GC是如何工作的,但是我们通常使用的JVM都是有GC的;Java的垃圾收集机制是为所有的Java应用进程服务的,并不单单是针对某一个特定的服务。

垃圾回收并不是一个独立的平台,它具有平台依赖性。

在Java语言中,判断一块内存空间时候符合垃圾收集器收集标准的标准只有一下两个:

  • 给对象赋予了空值null,以后在没有调用过。
  • 给对象赋予了新的值,即重新分配了内存空间。

注意:一块内存空间符合垃圾收集器 的收集标准,并不意味着这块内存空间就一定会被垃圾收集器收集。

我们在使用垃圾收集器时需要注意以下几点:

  • 不要试图去假定垃圾收集器发生的时间。这一切都是未知的
  • Java中提供了一些和垃圾收集机制打交道的类,而且提供了一种强制执行垃圾收集的方法—调用System.gc(),但这同样是一个不确定的方法,请求是一回事,能不能得到真正的执行垃圾收集还是一个未知数
  • 可以自己挑选合适自己的垃圾收集器
  • 对于频繁申请内存和释放内存的操作,还是要自己控制,最好使用finalize()强制执行比较好。

什么是Java中的内存泄露?

对于Java程序员来说,GC是透明的,不可见的。虽然有几个函数能够访问GC 根据Java语言规范定义,该函数不保证虚拟机的垃圾收集器一定会执行,因为不同的虚拟机实现者可能使用不同的算法进行管理,GC现成的优先级别比较低,虚拟机调用GC的策略有很多 ,但是执行垃圾回收会影响系统的性能。

垃圾收集器和内存分配策略:

一、 那些内存需要回收?

程序计数器、虚拟机栈和本地方法栈3个区域随线程而生,随线程而灭;栈中的栈帧随着方法的进入和退出有条不紊的执行着出栈和进栈的操作。每个栈帧分配多少内存基本上是在类结构确定下来时就已经确定了。因此这几个区域的内存分配和回收都具备确定性,在这几个区域就不需要过多的考虑回收的问题,因为方法或者线程 的结束内存自然就会被回收回去。

但是堆区域和方法区则不一样,这部分内存分配和回收都是动态的,垃圾收集器所关注的也主要是这部分区域的垃圾回收过程。

二、什么时候进行回收?

  1. 如何判断对象已死?
  • 引用计数算法:给对象添加一个引用计数器,每当有一个地方应用该对象的时候计数器的值就加1,当引用失效的时候计数器的值就减1,任何时候计数器的值为0的对象就是不能在被使用的对象。这种方法的实现比较简单判断的效率也很高,但是主流的虚拟机都不选择这种方法的主要原因就是它很难解决对象之间相互循环引用的问题。
  • 可达性分析算法:主流的商用语言中使用的一般是可达性分析算法来判断对象是否存活。这个算法的基本思路是通过一系列的被称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径成为引用链,当一个对象到GC Roots没有任何引用链相连的时候证明这个对象是不可用的,能被判定为可回收的对象。

在Java语言中,能作为GC Roots的对象包括以下几种:

  • 虚拟机栈中引用的对象;
  • 方法区中类静态属性应用的对象;
  • 方法区中常量引用的对象;
  • 本地方法栈中JNI(Native方法)引用的对象

Java对引用概念的划分:强引用、软引用、弱引用、虚引用。这四种引用强度一次逐渐减弱。

  • 强引用的对象永远不会被垃圾收集器回收掉。
  • 软引用是用来描述一些有用但并非必需的对象,对于软引用连接的对象在系统将会发生溢出之前会把这些对象列为可回收对象范围之内,如果这次回收还是没有足够的内存,才会发生溢出。
  • 弱引用也是用来描述非必需对象的,但是他的强度比软引用强度还要弱一些,被弱引用关联的对象只能生存到下一次垃圾收集之前。
  • 虚引用是最弱的一种引用关系。一个对象是否有虚引用的存在完全不会影响其生存时间,设置虚引用的唯一目的就是在这个对象被垃圾收集器回收的时候能得到一个系统通知。

  对方法区的回收:Java虚拟机规范中确实不要求虚拟机方法在方法区实现垃圾收集。而且在方法区的垃圾收集效率是比较低的,方法区(HotSpot的永久代)的垃圾收集主要回收两部分的内容:废弃常量和无用的类,通常判定一个常量是废弃的常量比较简单,但是要判定一个类是无用的类需要三个条件:该类所有的实例都已经被回收、加载该类的ClassLoader已经被回收、该类所对应的Class类没有在任何地方被引用。频繁自定义ClassLoader 的场景都需要虚拟机具备类卸载的功能。

三、  如何对这些需要回收的内存进行回收?

  可达性分析算法中不可达的对象也不一定会被回收,真正被回收需要经过两次标记过程。如果对象再经过可达性分析算法之后没有与GC Roots相连接的引用链,它会被第一次标记并进行一次筛选,筛选的条件就是此对象时候有必要执行finalize()方法。如果对象在该方法中重新与引用链建立了连接那就会被移除即将回收的集合,反之就会被真的回收。

四、垃圾收集算法:

1、标记-清除算法(mark-sweep):分为标记和清除两个阶段,首先标记出所有需要回收的对象,在标记完成之后统一回收所有被标记的对象。这是一种最基础的垃圾收集算法。这个算法的两个不足之处是:一个是效率问题,标记和清除的效率都不高、另一个是空间问题,标记清楚之后会产生大量的不连续的内存碎片,空间碎片过多可能会导致后边程序如果需要分配大的空间的时候无法找到满足条件的连续内存而不得不提前触发另一次的垃圾收集动作。

2、复制算法:为了解决效率问题,

Java基础知识--内存管理的更多相关文章

  1. JAVA基础知识之网络编程——-网络基础(Java的http get和post请求,多线程下载)

    本文主要介绍java.net下为网络编程提供的一些基础包,InetAddress代表一个IP协议对象,可以用来获取IP地址,Host name之类的信息.URL和URLConnect可以用来访问web ...

  2. Java平台与内存管理

    问题及答案来源自<Java程序员面试笔试宝典>第四章 Java基础知识 4.8Java平台与内存管理 1.为什么说Java是平台独立性语言? 平台独立性是指可以在一个平台上编写和编译程序, ...

  3. 沉淀,再出发:Java基础知识汇总

    沉淀,再出发:Java基础知识汇总 一.前言 不管走得多远,基础知识是最重要的,这些知识就是建造一座座高楼大厦的基石和钢筋水泥.对于Java这门包含了编程方方面面的语言,有着太多的基础知识了,从最初的 ...

  4. java基础知识精华

    转载:https://www.jianshu.com/p/6c078abb720f java基础知识 java内存模型 java运行时数据区域 hashMap 如何解决冲突 存储方式 冲突达到一定数量 ...

  5. java基础知识一览(二)

    一.java基础知识 1.一个文件中只能有一个public的类,因为他的类名要求和文件名相同. 2.classpath变量可以设置其它目录下的类. 例如:类文件所在目录是:F:\Javajdk,那么没 ...

  6. 「Java面试题/知识点精华集」20000+字的Java基础知识篇(2020最新版) !

    本文已经收录进我的 79K Star 的 Java 开源项目 JavaGuide:https://github.com/Snailclimb/JavaGuide (「Java学习+面试指南」一份涵盖大 ...

  7. java基础知识小总结【转】

    java基础知识小总结 在一个独立的原始程序里,只能有一个 public 类,却可以有许多 non-public 类.此外,若是在一个 Java 程序中没有一个类是 public,那么该 Java 程 ...

  8. JVM内存管理------JAVA语言的内存管理概述

    引言 内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑.不过世界上不存在十全十美的好事,在带来了便利的同时,也因此引入了很多令人抓 ...

  9. java 基础知识三 java变量

    java  基础知识 三 变量 1.作用域 {} 包围起来的代码 称之为代码块,在块中声明的变量只能在块中使用 2.常量 就是固定不变的量,一旦被定义,它的值就不能再被改变. 3.变量 变量必须在程序 ...

随机推荐

  1. Nancy 寄宿IIS

    一:简介 Nancy是一个轻量级的独立的框架,下面是官网的一些介绍: Nancy 是一个轻量级用于构建基于 HTTP 的 Web 服务,基于 .NET 和 Mono 平台,框架的目标是保持尽可能多的方 ...

  2. Go语言之匿名函数

    匿名函数和字面量函数一样, 凡是可以使用字面量函数的地方,都可以用匿名函数代替. 这个和js中的匿名函数差不多吧. package main import "fmt" var su ...

  3. [转] Mongoose简要API

    Mongoose是在node.js环境下对mongodb进行便捷操作的对象模型工具 因此,要使用mongoose,则必须安装node.js环境以及mongodb数据库.mongoose使mongodb ...

  4. Vs2017获取Git空仓库后创建解决方案及项目无法推送,推送失败的问题.

      与Git无关,因为远程是空文件夹,导致没有远程版本做对应提示更改或怎样,必须在创建人创建仓库的时候上传文件代码. https://developercommunity.visualstudio.c ...

  5. UICollectionView的常用方法

    class UICollectionView : UIScrollView //初始化,位置,风格 init(frame: CGRect, collectionViewLayout layout: U ...

  6. 浅析H5图片上传

    概述 最近需求上需要实现图片上传的功能,简单记录下实现过程.目前实现的功能比较简单,主要有以下几点: 图片预览 图片删除 拖拽上传 压缩上传 移动端实现方案:使用File API 主要使用到 File ...

  7. jQuery选择器总结 jQuery 的选择器可谓之强大无比,这里简单地总结一下常用的元素查找方法

    新年第一编文章 jQuery 的选择器可谓之强大无比,这里简单地总结一下常用的元素查找方法   $("#myELement")    选择id值等于myElement的元素,id值 ...

  8. device not found解决方案

    今天在使用cordova tools进行真机调试的,报了一个错:device not found; 字面意思就是没有发现设备,这时候可以首先尝试重启adb服务 C:\Users\username\Ap ...

  9. 需求:lr需要在一串数字中随机位置插入一个新数字的实现方式

    效果如下: 需要用到sscanf()函数:  从一个字符串中读进与指定格式相符的数据. Action() { ],s2[],s3[]; int n=atoi(lr_eval_string(" ...

  10. 函数对象的call()、apply() 方法区别

    函数对象的call().apply() 方法 函数作为对象提供了call(),apply() 方法,他们也可以用来调用函数,这两个方法都接受一个对象作为参数,用来指定本次调用时函数中this的指向: ...