【Java虚拟机】JVM垃圾回收器详解

news2024/11/24 4:55:30

1.什么是垃圾收集器

  • 垃圾回收算法是内存回收的方法论,垃圾收集器则是内存回收的具体实现

  • 目前Java规范中并没有对垃圾收集器的实现有任何规范

  • 不同的厂商、不同的版本的虚拟机提供的垃圾收集器是不同的,主要讨论的是HotSpot虚拟机

  • 不存在最厉害的垃圾收集器,只有在对应场景中最合适的垃圾收集器

  • 为什么要有很多收集器?

    • 因为Java的使用场景很多,移动端,服务器等,然后内存里面对象存活时间不一样
    • 需要针对不同的场景,提供不同的垃圾收集器,提高垃圾收集的性能

2.垃圾收集器分类

(1)新生代垃圾回收器

  • Serial 串行垃圾回收器

  • ParNew 年轻代并发垃圾回收器

  • Parallel并行垃圾回收器

(2)老年代垃圾回收器

  • Serial Old 串行老年代垃圾器
  • Parallel Old 老年代的并行垃圾回收器
  • CMS (ConcMarkSweep)并发标记清除

(3)整堆收集器:G1、ZGC

2.图解分配垃圾收集器的组合

  • JDK8中默认使用: Parallel Scavenge GC + ParallelOld GC
  • JDK14 弃用了: Parallel Scavenge GC + Parallel OldGC
  • JDK9默认是用G1为垃圾收集器
  • JDK14 移除了 CMS GC

在这里插入图片描述

  • 年轻代与年老代的垃圾回收器组合

3.垃圾收集器关注的核心指标

  • 吞吐量
    • 运行用户代码的时间占总运行时间的比例(总运行时间 = 程序的运行时间 + 内存回收的时间)
    • 例子:虚拟机共运行100分钟,垃圾收集器花掉1分钟,那么吞吐量就是99%
  • 暂停时间
    • 执行垃圾收集时,程序的工作线程被暂停的时间
    • 一个时间段内应用程序线程暂停,让GC线程执行的状态
    • GC期间100毫秒的暂停时间,说明在这100毫秒期间内没有应用程序线程是活动的
  • 收集频率
    • 指垃圾回收器多长时间会运行一次。一般来说,垃圾回收器的频率应该是越低越好。

4.Serial收集器详解

  • Serial是最简单的垃圾收集器,使用单线程进行垃圾收集,暂停所有应用程序线程, 在单核CPU环境来说,Serial收集器更高效
  • Serial Old是Serial收集器的老年代版本,在jdk1.5之前的版本与Parallel收集器搭配使用,或者作为CMS的备选方案
  • 适用于小型应用程序和客户端应用程序,一般javaweb、springboot项目不会采用这类收集器
  • 新生代采用复制算法,老年代采用标记整理算法
  • 相关命令参数使用
    • 同时指定年轻代和老年代都使用串行垃圾收集器 -XX:+UseSerialGC
    • 查看命令行相关参数 -XX:+PrintCommandLineFlags
//参数
-XX:+UseSerialGC -XX:+PrintCommandLineFlags -Xms32m -Xmx32m

//输出
-XX:InitialHeapSize=33554432 -XX:MaxHeapSize=33554432 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseSerialGC 

在这里插入图片描述

5.ParNew收集器详解

  • 工作在年轻代上的,只是将串行的垃圾收集器改为了并行,其他基本和Serial一样,使用多个线程进行垃圾回收的
  • 适用于大型应用程序和多核处理器,以及在服务端应用程序中使用,单核上效率比Serial低
  • 和下集讲Parallel收集器类似,但Parallel收集器不兼容CMS,除了它只有Serial收集器可以和CMS收集器配合工作
  • 新生代采用复制算法,老年代采用标记整理算法
  • 相关命令参数使用
    • 年轻代使用ParNew回收器,老年代使用串行收集器 -XX:+UseParNewGC
    • 查看命令行相关参数 -XX:+PrintCommandLineFlags
  //参数
  -XX:+UseParNewGC -XX:+PrintCommandLineFlags -Xms32m -Xmx32m

  //输出  
  -XX:InitialHeapSize=33554432 -XX:MaxHeapSize=33554432 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParNewGC 

在这里插入图片描述

6.Parallel收集器详解

  • Parallel全称 Parallel Scavenge 是一种多线程垃圾收集器,和ParNew收集器类似,是一个新生代收集器

  • 默认线程数和cpu核数一样,用于大型应用程序和服务器应用程序,比如大批量数据处理,后台计算任务等

  • Parallel Old是Parallel Scavenge收集器的老年代版本,JDK8默认使用Parallel Scavenge收集器

  • 算法:新生代采用复制算法,老年代采用标记整理算法

  • Parallel对比ParNew

    • -XX:+UseParallelGC 仅对年轻代有效,不可以和CMS收集同时使用
    • -XX:+UseParNewGC 设置年轻代为多线程收集,可以和CMS收集同时使用
  • 相关命令参数使用

    • 年轻代使用ParallelGC垃圾回收器,老年代使用串行回收器 -XX:+UseParallelGC

    • 年轻代使用ParallelGC垃圾回收器,老年代使用ParallelOldGC垃圾回收器 -XX:+UseParallelOldGC

    • 查看命令行相关参数 -XX:+PrintCommandLineFlags

//参数
-XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+PrintCommandLineFlags -Xms32m -Xmx32m

//输出
-XX:InitialHeapSize=33554432 -XX:MaxHeapSize=33554432 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC -XX:+UseParallelOldGC 

在这里插入图片描述

7.CMS收集器详解

  • CMS 全称 Concurrent Mark Sweep,是一款并发的、使用标记-清除算法的垃圾回收器
  • 老年代中的对象生命周期较长,垃圾回收频率较低,目标是获取最短垃圾收集停顿时间,针对 老年代 垃圾的收集器
  • 停顿时间较短,适合对响应时间要求较高的应用程序,如Web应用程序、电子商务等高并发场景
  • 整个过程分4步**(初始标记 和 重新标记 需要stopTheWorld,并发标记与并发清除阶段不需要暂停用户线程)**
    • 初始标记: 标记GC Root直接关联对象,会导致stopTheWorld
    • 并发标记: 与用户线程同时运行
    • 重新标记:会导致stopTheWorld
    • 并发清除:与用户线程同时运行

在这里插入图片描述

  • 相关命令参数使用

    • 年轻代使用ParNew垃圾回收器,老年代使用CMS回收器 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
    • 查看命令行相关参数 -XX:+PrintCommandLineFlags
//输入
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+PrintCommandLineFlags -Xms32m -Xmx32m

//输出
-XX:InitialHeapSize=33554432 -XX:MaxHeapSize=33554432 -XX:MaxNewSize=11190272 -XX:MaxTenuringThreshold=6 -XX:NewSize=11190272 -XX:OldSize=22364160 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseConcMarkSweepGC

8.G1收集器详解

  • Garbage First 垃圾收集器是JDK7版本之后引入的一种垃圾回收器,jdk9中将G1变成默认的垃圾收集器
  • 可以在不同的内存区域中分配垃圾回收的工作,提高了垃圾回收效率
  • JDK11中查看默认垃圾收集器
    • -XX:+PrintCommandLineFlags 查看命令行相关参数(包含使用的垃圾收集器)
-XX:G1ConcRefinementThreads=9 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=536870912 -XX:MaxHeapSize=8589934592 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC
  • 核心原理

    • 保留了分代思想,把内存划分为多个独立的区域Region,区域中包含逻辑上的年轻代、老年代区域

    • 取消了年轻代、老年代的物理划分,不用单独对每个年代空间进行设置

    • Region的区域类型是动态变化的,可能之前是年轻代,经过了垃圾回收之后就变成了老年代,实现更加精细化的垃圾回收

    • 整体采用标记整理算法, 局部是采用复制算法,不会产生内存碎片

    • 把整个Java堆划分成约2048个独立Region块,每个Region块大小根据堆空间的大小而定,为2的N次幂,1MB~32MB

      • 每个Region的大小可通过参数 -XX:G1HeapRegionSize 配置
    • 新增加一种叫Humongous内存区域,用于存储大对象

    • 如果超过1.5个region,就是巨型对象,就放到H区,默认直接会被分配在老年代,一般被视为老年代.图中的H块

    • 如果一个H区装不下一个巨型对象,G1会寻找连续的H区来存储,为了能找到连续的H区,有时需要启动Full GC

在这里插入图片描述

  • G1提供三种模式垃圾回收模式

    • Young GC
      • G1与之前垃圾收集器的Young GC不同,不是当新生代的Eden区放满了就进行垃圾回收
      • G1会计算当前Eden区回收大概需要多久时间,如果接近参数-XX:MaxGCPauseMills设定的值,会触发Young GC
      • 回收过程也是将Eden区和Survivor区中的存活对象复制到空闲的Survivor区,并清空Eden区和原来的Survivor区。
      • 如果Survivor区也满了,那么会将存活对象复制到Old区。在Young GC期间,应用程序会被暂停
    • Mixed GC
      • 多数对象晋升到老年代old region时,为了避免堆内存被耗尽问题,会触发混合的GC
      • 回收整个Young Region,还会回收一部分的Old Region区域,注意不是全部Old Region区域
      • 触发条件
        • 参数 -XX:InitiatingHeapOccupancyPercent=n 决定
        • 默认:45%,即 当老年代大小占整个堆大小百分比达到该阀值时触发
    • Full GC
      • 单个线程会对整个堆的所有代中所有分区做标记、清除以及压缩动作,非常耗时
    • 总结
      • 在Young GC和Mixed GC中,G1垃圾收集器都会对每个Region的存活对象数量进行统计,
      • 根据存活对象数量和空闲Region的数量,动态地决定垃圾收集的区域和顺序
      • 这种动态的垃圾收集策略,可以避免Full GC的发生,提高了应用程序的响应速度
  • G1的MixGC垃圾收集分为下面几个步骤

    • 初始标记(STW)

      • 记录下GC Roots能直接引用的对象,并标记所有存活的对象,会执行一次年轻代GC,需要暂停所有线程,速度很快
    • 并发标记

      • 与应用线程一起工作,进行可达性分析
      • g1收集器会对堆内存进行并发标记,找出所有存活的对象,并记录它们所在的Region
    • 最终标记(STW)

      • 修正并发标记期间, 部分因程序运行导致发生变化的那一部分对象,根据算法修复一些引用的状态
    • 筛选回收(STW)

      • 对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿STW时间,即 -XX:MaxGCPauseMillis 制定计划
      • 成本排序案例
        • 现在有Region1、Region2和Region3三个区域
          • Region1预计可以回收1.5MB内存,预计耗时2MS,投产比ROI=1.5/2
          • Region2预计可以回收1MB内存,预计耗时1MS,投产比ROI=1/1
          • Region3预计可以回收0.5MB内存,预计耗时1MS,投产比ROI=0.5/1
        • 那Region1、Region2和Region3各自的回收价值与成本比值分别是:0.75、1和0.5,
        • 比值越高说明同样的付出收益越高,如果此时只能回收一个Region的内存空间,G1就会选择Region2进行回收
        • 保证了G1收集器在有限的时间内尽可能地提高收集效率

在这里插入图片描述

  • 配置G1收集器的相关参数

    • -XX:+UseG1GC
      • 启用G1垃圾收集器。
    • -XX:G1HeapRegionSize=n
      • Java 堆大小划 分出约 2048 个区域,默认是堆内存的1/2000;配置需要为2的N次幂,1MB~32MB
      • 使用G1垃圾回收器最小堆内存应为 1MB*2048=2GB ,低于这个的建议使用其它垃圾回收器。
    • -XX:MaxGCPauseMillis=n
      • 设置最大停顿时间,单位为毫秒,默认为200毫秒(JVM会尽力实现,但不能保证达到)
    • -XX:ParallelGCThreads=n
      • 设置 STW 工作线程数的值。一般设置为逻辑处理器的数量,最多为 8
      • 是在STW阶段,并行执行【垃圾收集动作】的线程数
    • -XX:ConcGCThreads=n
      • 在【并发标记】阶段,并发执行标记的线程数,一般将 n 设置为并行垃圾回收线程数 (ParallelGCThreads) 的 1/4
    • -XX:InitiatingHeapOccupancyPercent=n
      • 设置G1 Mix垃圾回收的触发阈值,默认为45%
  • 参数测试

//输入
-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -Xms524m -Xmx524m -XX:+PrintCommandLineFlags 

//输出
-XX:G1ConcRefinementThreads=9 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=549453824 -XX:MaxGCPauseMillis=100 -XX:MaxHeapSize=549453824 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC
  • G1收集器应用场景

    • 大型应用程序:可以将堆内存划分为多个区域,以实现更加精细化的垃圾回收。
    • 高并发、低延迟:对响应时间要求较高的应用程序,如Web应用程序、电子商务等高并发场景
    • 大内存应用:可以在垃圾回收过程中释放大量的空间,提高了内存的利用率。
  • 使用G1垃圾收集器注意事项

    • 不手工设置年轻代大小

      • 比如使用 -Xmn 选项或 -XX:NewRatio 等设置年轻代大小
    • 暂停时间的目标不要太小

      • G1 的吞吐量目标是 90% 的应用程序时间和 10%的垃圾回收时间
      • 如果把停顿时间调得非常低, 如设置为10毫秒, 很可能出现的结果就是由于停顿目标时间太短
      • 导致每次回收内存只占堆内存很小的一部分, 收集器收集的速度跟不上分配器分配的速度, 导致垃圾慢慢堆积
      • 应用运行时间一长就占满堆引发Full GC反而降低性能, 通常把期望停顿时间设置为一两百毫秒是比较合理的
    • 避免存活时间短的大对象

      • G1垃圾收集器对程序的代码质量要求较高,需要对程序的内存使用情况进行精细化管理,对应用程序的代码进行优化和调整

9.ZGC收集器详解

  • Z Garbage Collector 是Oracle公司开发一种可伸缩、低停顿时间的垃圾收集器,标记-复制算法(进行了改进)
  • 垃圾回收过程几乎全部是并发,实际STW停顿时间极短,停顿时间控制10ms内,主要采用的染色指针和读屏障技术
  • 在 JDK 11 中是实验性的特性引入,在 JDK 15 中 ZGC 可以正式投入生产使用,使用 –XX:+UseZGC 启用
  • ZGC 的堆内存也是基于 Region 来分布,和G1类似,不区分新生代老年代的,Region 支持动态地创建和销毁,大小不是固定
  • 三种类型的 Region
    • 小型页面 Small Region:容量固定2MB,主要用于放置小于 256 KB 的小对象。
    • 中型页面Medium Region:容量固定32MB,主要用于放置大于等于 256 KB 小于 4 MB 的对象。
    • 大型页面Large Region
      • 容量不固定 为N * 2MB, Region 是可以动态变化的,但必须是 2MB 的整数倍,最小支持 4 MB

在这里插入图片描述

  • 特点

    • 低停顿时间
      • ZGC最大的特点是在不增加延迟的情况下,能够处理非常大的内存数据
      • 可以将停顿时间限制在10ms以内,对于需要快速响应的应用程序来说是非常重要
    • 可伸缩性
      • 可以处理非常大的内存数据,适应不同规模的应用程序,从小型应用程序到大型企业级应用程序
    • 不需要分代
      • 不需要将内存分为新生代和老年代,不需要复杂的内存回收算法
    • 并发处理
      • 采用了并发处理的方式来进行垃圾回收可以在应用程序运行的同时进行垃圾回收
  • 工作流程

    • 初始标记(STW):找 GC Roots 直接引用的对象,处理时间和GC Roots的数量成正比,停顿时间不随着堆的大小而增加。

    • 并发标记(没有STW):扫描剩余的所有对象,处理时间比较长,业务线程与GC线程同时运行,但这个阶段会有漏标问题

    • 再标记(STW):通过算法解决漏标对象,和G1中的解决漏标的算法类似

    • 并发转移准备(没有STW) :分析最有回收价值GC分页,即ROI计算

    • 初始转移(STW):转移初始标记的存活对象和做对象重定位,时间和GC Roots的数量成正比,时间不随堆的大小而增加。

    • 并发转移(没有STW):对转移并发标记的存活对象做转移

在这里插入图片描述

  • 平台支持说明

    • 部分版本里面是实验性参数,需要加 -XX:+UnlockExperimentalVMOptions 才可以使用
是否支持平台支持版本
Linux/x64JDK 15 (Experimental since JDK 11)
Linux/AArch64JDK 15 (Experimental since JDK 13)
macOS/x64JDK 15 (Experimental since JDK 14)
Windows/x64JDK 15 (Experimental since JDK 14)
Windows/AArch64JDK 16
macOS/AArch64JDK 17
Linux/PowerPCJDK 18
  • JDK17环境下验证参数
参数: -XX:+UseZGC -XX:+PrintCommandLineFlags -Xms32m -Xmx32m

输出结果
-XX:InitialHeapSize=33554432 -XX:MaxHeapSize=33554432 -XX:MinHeapSize=33554432 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:-UseCompressedOops -XX:+UseZGC 

总结:ZGC业界还没大规模使用,更多再实验性观望阶段,还存在变动和争议阶段,如果可能则预计26年~28年成为主流,当下我们开发的采用的垃圾收集器是G1收集器,23~25年会是主流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/488969.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java】内部类Object类

目录 1.内部类 1.1实例内部类 1.2静态内部类 1.3局部内部类 1.4匿名内部类 2.Object类 2.1getClass方法 2.2equals方法 2.3hashcode方法 1.内部类 定义:一个类定义在另一个类或一个方法的内部,前者称为内部类,后者称为外部类。 分…

JWT渗透与防御

JWT渗透与防御 什么是JWTJWT漏洞介绍工具使用 身份认证(Authentication)又称鉴权,是指通过一定的手段,完成对用户身份的确认。认证的方式:sessioncookie、JWT、Token session认证的局限性 session认证机制需要配合cookie才能实现。由于cookie…

238页9万字大数据治理与服务平台建设及数据服务实施方案(word)

本资料来源公开网络,仅供个人学习,请勿商用,如有侵权请联系删除。 1 项目解决方案 1.1 建设类业务技术方案 1.1.1 业务需求分析 根据对招标要求的理解,建设业务需求主要包括如下几个方面: (1&#xff…

网站遭遇XSS注入如何排查及解决

首先要明白什么是XSS注入 存储型 XSS 的攻击步骤: 攻击者将恶意代码提交到目标网站的数据库中。用户打开目标网站时,网站服务端将恶意代码从数据库取出,拼接在 HTML 中返回给浏览器。用户浏览器接收到响应后解析执行,混在其中的…

Docker部署spring boot项目

在docker部署时首先要保证一般部署能够访问。 docker命令部署spring boot项目 目前主流的java框架为spring,软件包为jar包,只需以jar为基础构建容器环境。打包为jar后只需要jvm就可以运行,因此需要以jdk为镜像构建容器。 基于命令构建jdk环…

MySQL面试八股文:索引篇

索引的定义 索引是数据库中用来加速数据查询的一种数据结构。它可以将数据表中的某一列或多列进行排序,以便快速查找数据,减少数据库的扫描次数,提高查询速度。 索引的优缺点 索引的优点是可以大幅度提高数据查询的速度,尤其是…

( 数组和矩阵) 565. 数组嵌套 ——【Leetcode每日一题】

❓565. 数组嵌套 难度:中等 索引从 0 开始长度为N的数组 A,包含 0 到 N - 1 的所有整数。找到最大的集合 S并返回其大小,其中 S[i] {A[i], A[A[i]], A[A[A[i]]], ... } 且遵守以下的规则。 假设选择索引为 i 的元素 A[i] 为 S 的第一个元…

【Java|golang】1003. 检查替换后的词是否有效

给你一个字符串 s ,请你判断它是否 有效 。 字符串 s 有效 需要满足:假设开始有一个空字符串 t “” ,你可以执行 任意次 下述操作将 t 转换为 s : 将字符串 “abc” 插入到 t 中的任意位置。形式上,t 变为 tleft “…

【软考高项笔记】第1章 信息化发展1.3 现代化创新发展

1.3 现代化创新发展 1.3.1 农业农村现代化 采棉机,传感器检查温度湿度 乡村振兴战略 建设基础设施 发展智慧农业 建设数据乡村1.3.2 两化融合与智能制造(工业) 信息化 工业化 发展战略 坚持自主可控,安全高效,推进产业…

VESC操作入门——双轮毂电机控制和CAN通信

目录 一、VESC驱动轮毂电机1.1、硬件准备1.2、硬件接线1.3、校准电机1.4、主操作界面 二、CAN通信2.1、硬件连接2.2、代码说明2.3、发送指令 三、双轮毂电机3.1、校准第二个电机参数3.2、硬件连接3.3、CAN总线发送指令 四、把VESC做为USB转CAN模块 ODrive、VESC和SimpleFOC 教程…

【星戈瑞】Sulfo-Cyanine5 mal 磺酸跟水溶性生物标记试剂

水溶性Sulfo-Cyanine5 mal是一种用于生物标记和荧光成像的荧光染料。它的化学名称是Cyanine5 maleimide,分子式为C29H27ClN2O4S,分子量为576.05。Cyanine5 mal属于Cyanine染料家族,具有强烈的吸收和发射光谱,适用于生物分子的标记…

( 数组和矩阵) 769. 最多能完成排序的块 ——【Leetcode每日一题】

❓769. 最多能完成排序的块 难度:中等 给定一个长度为 n 的整数数组 arr ,它表示在 [0, n - 1] 范围内的整数的排列。 我们将 arr 分割成若干 块 (即分区),并对每个块单独排序。将它们连接起来后,使得连接的结果和按升序排序后…

云服务器vCPU和CPU有什么区别?

云服务器的vCPU和物理服务器的CPU有什么区别?阿里云百科以阿里云服务器ECS为例, 阿里云服务器vCPU和CPU是什么意思?CPU和vCPU有什么区别?一台云服务器ECS实例的CPU选项由CPU物理核心数和每核线程数决定,CPU是中央处理…

推荐算法实战项目:FNN 原理以及案例实战(附完整 Python 代码)

本文要介绍的是FNN模型,出自于张伟楠老师于2016年发表的论文《Deep Learning over Multi-field Categorical Data》。 论文提出了两种深度学习模型,分别叫做FNN(Factorisation Machine supported Neural Network)和SNN&#xff0…

如何利用 Kotlin 特性封装 DataStore

Jetpack DataStore是一种数据存储解决方案,由于使用了 Kotlin 协程或者 RxJava 以异步、一致的事务方式存储数据,用法相较于其它存储方案 (SharedPreferences、MMKV) 会更加特别,所以目前网上都没有什么比较好的 DataStore 封装。 个人了解了…

(十)Shapefile文件创建——创建Shapefile和dBASE

(十) Shapefile文件创建——创建Shapefile和dBASE ArcCatalog 可以创建新的 Shapefile 和 dBASE表,并可进行属性项及索引的操作定义 Shapefile 的坐标系统。当在目录中改变 Shapefile 的结构和特性 (Properties)时必须使用 ArcMap 来更新或重…

动态规划 --- 01背包

动态规划 — 01背包 一直到现在都非常害怕动态规划,因为基本上自己都无法想出dp递推式,太难受了 T.T 今天再一次遇到了需要写01背包的情况,根据自己学习的一点点经历,再稍微总结一下01背包吧,虽然是个被认为dp入门的…

自学Python必须知道的优秀社区

国内学习Python网站: 知乎学习平台:Python - 基础入门 - 知学堂黑马程序员视频库:大数据学习路线2023版-黑马程序员大数据学习路线图菜鸟教程:菜鸟教程 - 学的不仅是技术,更是梦想!极客学院:极…

香港服务器租用攻略:如何优化用户体验?

服务器是网站、应用程序和其他在线内容的核心,对于在线业务来说是至关重要的。如今,随着互联网的普及和数字化转型,越来越多的企业选择在香港租用服务器,以满足其业务需求。但是,租用服务器并不仅仅是选择一个服务商并…

让chatGPT给我写一个CSS,我太蠢了

前言 CSS这东西,让AI写的确有点难度,毕竟它写出来的东西,没办法直接预览,这是其次。重要的是CSS这东西怎么描述,不好描述啊,比如我让他给我制作一个这样的效果出来,没办法描述,所以…