jvm GC收集器与内存分配策略

转载至:http://www.lai18.com/content/2531743.html什么叫垃圾?垃圾是怎样产生的?垃圾怎么回收?

  1. java和C、C++中的垃圾区别
    C和C++中的对象生存周期完全有编程者决定,而java中对象的生存周期默认由虚拟机决定,但是也允许编程者显式的调用gc()方法。因此对于java开发人员,我们可以肆意妄为的new对象,而不用管理对象的生存周期,这对于编程自然是方便的。不过,要想让程序更好的运行,我们就要理解java中的对象生存周期,从创造到被销毁的整个过程。下面就浅析一下java的对象生命周期。
  2. 谈引用(理解对象的存在)
    在谈到对象的时候,就离不开引用(和c++中的指针很类似),在创建对象的时候,会在虚拟机栈中新建一块内存地址,此内存地址中存储的是对象的引用(reference类型)地址,指向java堆中或者方法区的常量池中的对象(这个对象是真实存在的,我们要进行操作的对象)。
    在jdk1.2之后,java对引用进行扩充。分为以下四种:
    • ①强引用(Strong Reference):如“Object obj = new Object()”,这类引用是 Java 程序中最普遍的。只要强引用还存在,垃圾收集器就永远不会回收掉被引用的对象。
    • ②软引用(Soft Reference):它用来描述一些可能还有用,但并非必须的对象。在系统内存不够用时,这类引用关联的对象将被垃圾收集器回收。JDK1.2 之后提供了 SoftReference 类来实现软引用。
    • ③弱引用(Weak Reference):它也是用来描述非需对象的,但它的强度比软引用更弱些,被弱引用关联的对象只能生存岛下一次垃圾收集发生之前。当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。在 JDK1.2 之后,提供了 WeakReference 类来实现弱引用。
    • ④虚引用(Phantom Reference):最弱的一种引用关系,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的是希望能在这个对象被收集器回收时收到一个系统通知。JDK1.2 之后提供了 PhantomReference 类来实现虚引用。
      注:四种引用的解释参考《深入理解Java虚拟机》,小伙伴们可以当做扩展,实际工作中很少会用到。
  3. 对象的创建后的状态以及发展
    先贴一张图
    java堆参考上一篇《深入理解JVM之基本构架》
    • ①新对象当我们创建一般对象后,对象优先会存在【Eden】新生代中。
    • ②大对象直接进入老年代。
      大对象的含义:长字符串、数组等。在开发中应尽量避免使用大对象。因为大对象的存在会导致老年代空间提前触发【Full GC】,而【Full GC】的速度一般都会比较慢, 并且【Full GC】会导致Stop The World。
    • ③长期存活的对象将进入老年代。
      每一个对象都有一个对象年龄计数器。如果Eden中的对象经过一次【Minor GC】就会进入【Survivor】中,并且计数器变成1。每当发生一次【Minor GC】后,计数器就会加1,当到达一定的程度后,该对象就会晋升到【Old】老年代中。

注解:【Minor GC】和【Full GC】的区别

【Minor GC】(新生代GC):发生在【Eden Space】区域的垃圾回收,因为java中的对象存在的时间比较短,因此【Minor GC】是非常频繁的,而且速度也会很快。
【Full GC】(老年代GC)【Major GC】:前面三个名词属于一个意思,只是不同的叫法而已。指发生在【Old Space】区域的垃圾回收,【Full GC】的过程比较慢,大概是【Minor GC】的10倍以上,而且会伴随一次Stop-The-World。

解释stop-the-World

在开始学习GC之前你应该知道一个词:stop-the-world。不管选择哪种GC算法,stop-the-world都是不可避免的。Stop-the-world意味着从应用中停下来并进入到GC执行过程中去。一旦Stop-the-world发生,除了GC所需的线程外,其他线程都将停止工作,中断了的线程直到GC任务结束才继续它们的任务。GC调优通常就是为了改善stop-the-world的时间。

  1. 分析对象怎么变成垃圾的? 什么时候垃圾可以回收?
    java采用可达性分析算法,我们就不管它是什么算法,我们要知道的是什么时候对象变成垃圾了。
    先贴图说话GC
    在上图中,有一个GC ROOT Set区域,此区域中,下面的对象,无论通过多少个引用,只要能指向GC Roots的引用,此对象,就不会被回收。也就是从【GC Roots】到这个对象不可达时,此对象就变成了垃圾。而可以作为【GC Roots】的对象包括如下四种:
    • ①虚拟机栈(栈桢中的本地变量表)中的引用的对象
    • ②方法区中的类静态属性引用的对象
    • ③方法区中的常量引用的对象
    • ④本地方法栈中JNI的引用的对象
      但是要记住垃圾归垃圾,它并没有死亡,也没有被回收,只有发生【Minor GC】或者【Full GC】时才可能被回收。
      1. 简介垃圾收集算法
    • ①标记 - 清除算法(Mark-Sweep)标记清除
      首先标记三种标记的内存状态,标记完成后,只是把【可回收内存】清除掉就可以了,这种算法就是简单的【标记-清除算法】。
    • ②标记 - 整理算法(Mark-Compact)标记整理
      首先标记三种标记的内存状态,这个步骤和标记-清除算法一样。标记完成后,把【存活对象】移向一端,然后直接清理掉边界以外的内存,这种算法就是【标记-整理算法】。
    • ③复制算法复制算法

这种算法会浪费一半的内存空间,我们称为A、B两块空间。当使用A空间的时候,B空闲,每当A空间使用完后,就将存活对象复制到B空间中,并将A中的空间清理掉。这样每次都是对一半的内存进行内存回收。小伙伴们想一下,一半的空间都在浪费,这是无法承受的。因此,就出现了【分代收集算法】。

  • ④分代收集算法
    分代收集算法,就不贴图了,请看第一个图片。有【Eden】【S0】【S1】【Old】
    因为在新生代中大多数对象都是“朝生夕死”的,因此不必要按照“1:1”的比例来分配空间,HotSpot虚拟机按照【Eden】:【S0】:【S1】=8:1:1的比例来配备内存,先说一下过程,首先使用【Eden】和【S0】,当回收时,将存活对象复制到【S1】中,并整理【Eden】和【S0】;以此往复。如果【S1】中的内存小于存活对象需要的内存的时候(【S1】空间不够用的时候),就借用【Old】的内存来担保。
    1. 分析HotSpot的垃圾收集器(参考《深入理解Java虚拟机》P75)
      垃圾收集器
      Serial
  • ①Serial
  • ②Serial Old
    Serial收集器是一个单线程的收集器,但它的“单线程”的意义并不仅仅说明它只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是在它进行垃圾收集时,必须暂停其他所有的工作线程,直到它收集结束。Stop -The -World
    Serial Old是Serial收集器的老年代版本,它同样是一个单线程收集器,使用标记-整理算法。
    ParNew
    -③ParNew
    是Serial的多线程版本。和(CMS或者Serial Old配合工作。
    Parallel
  • ④Parallel Scavenge
  • ⑤Parallel Old
    Parallel Scavenge收集器是一个新生代收集器,它也是使用复制算法的收集器,又是并行的多线程收集器。Parallel Scavenge收集器的目标则是达到一个可控制的吞吐量(Throughput)。
    Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。
    CMS
    -⑥CMS(Concurrent Mark Sweep)
    CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。目前很大一部分的Java应用集中在互联网站或者B/S系统的服务端上,这类应用尤其重视服务的响应速度,希望系统停顿时间最短,以给用户带来较好的体验。CMS收集器就非常符合这类应用的需求。
    -⑦G1(Garbage First)
    G1(Garbage-First)是一款面向服务端应用的垃圾收集器。HotSpot开发团队赋予它的使命是未来可以替换掉JDK 1.5中发布的CMS收集器。与其他GC收集器相比,G1具备如下特点。并行与并发;分代收集;空间整合;可预测的停顿。
    在G1之前的其他收集器进行收集的范围都是整个新生代或者老年代,而G1不再是这样。使用G1收集器时,Java堆的内存布局就与其他收集器有很大差别,它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,它们都是一部分Region(不需要连续)的集合。

在使用Python来安装geopandas包时,由于geopandas依赖于几个其他的Python库(如GDAL, Fiona, Pyproj, Shapely等),因此安装过程可能需要一些额外的步骤。以下是一个基本的安装指南,适用于大多数用户: 使用pip安装 确保Python和pip已安装: 首先,确保你的计算机上已安装了Python和pip。pip是Python的包管理工具,用于安装和管理Python包。 安装依赖库: 由于geopandas依赖于GDAL, Fiona, Pyproj, Shapely等库,你可能需要先安装这些库。通常,你可以通过pip直接安装这些库,但有时候可能需要从其他源下载预编译的二进制包(wheel文件),特别是GDAL和Fiona,因为它们可能包含一些系统级的依赖。 bash pip install GDAL Fiona Pyproj Shapely 注意:在某些系统上,直接使用pip安装GDAL和Fiona可能会遇到问题,因为它们需要编译一些C/C++代码。如果遇到问题,你可以考虑使用conda(一个Python包、依赖和环境管理器)来安装这些库,或者从Unofficial Windows Binaries for Python Extension Packages这样的网站下载预编译的wheel文件。 安装geopandas: 在安装了所有依赖库之后,你可以使用pip来安装geopandas。 bash pip install geopandas 使用conda安装 如果你正在使用conda作为你的Python包管理器,那么安装geopandas和它的依赖可能会更简单一些。 创建一个新的conda环境(可选,但推荐): bash conda create -n geoenv python=3.x anaconda conda activate geoenv 其中3.x是你希望使用的Python版本。 安装geopandas: 使用conda-forge频道来安装geopandas,因为它提供了许多地理空间相关的包。 bash conda install -c conda-forge geopandas 这条命令会自动安装geopandas及其所有依赖。 注意事项 如果你在安装过程中遇到任何问题,比如编译错误或依赖问题,请检查你的Python版本和pip/conda的版本是否是最新的,或者尝试在不同的环境中安装。 某些库(如GDAL)可能需要额外的系统级依赖,如地理空间库(如PROJ和GEOS)。这些依赖可能需要单独安装,具体取决于你的操作系统。 如果你在Windows上遇到问题,并且pip安装失败,尝试从Unofficial Windows Binaries for Python Extension Packages网站下载相应的wheel文件,并使用pip进行安装。 脚本示例 虽然你的问题主要是关于如何安装geopandas,但如果你想要一个Python脚本来重命名文件夹下的文件,在原始名字前面加上字符串"geopandas",以下是一个简单的示例: python import os # 指定文件夹路径 folder_path = 'path/to/your/folder' # 遍历文件夹中的文件 for filename in os.listdir(folder_path): # 构造原始文件路径 old_file_path = os.path.join(folder_path, filename) # 构造新文件名 new_filename = 'geopandas_' + filename # 构造新文件路径 new_file_path = os.path.join(folder_path, new_filename) # 重命名文件 os.rename(old_file_path, new_file_path) print(f'Renamed "{filename}" to "{new_filename}"') 请确保将'path/to/your/folder'替换为你想要重命名文件的实际文件夹路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值