为什么Java有GC调优而没听说过有CLR的GC调优?

前言

在很多的场合我都遇到过一些群友提这样的一些问题:

  • 为什么Java有GC调优而CLR没有听说过有GC调优呢?

  • 到底是Java的JVM GC比较强还是C#使用的.NET CLR的GC比较强呢?
    其实业内已经有几位大佬的高赞文章和大家分享一下,主要讨论JVM和CLR还有GC调优,今天就借用大佬的回答给大家分享一下。

R大的回答

首先给大家介绍一下R大,R大网名叫RednaxelaFX,南京大学毕业巨佬,主攻高级编程语言虚拟机的设计与实现,对于C# .NET CLR有非常深入的研究和了解。先后加入阿里、Oracle、Azul System从事JVM虚拟机开发的工作(HotSpot JVM and Zing JVM)。现在在Databricks从事Spark开发工作。

R大社交主页

iteye博客:https://www.iteye.com/blog/user/rednaxelafx
知乎主页: https://www.zhihu.com/people/rednaxelafx
GitHub: https://github.com/rednaxelafx

R大回答相关问题摘抄

为什么听说过 JVM 调优,却没听说过 CLR 调优?

RednaxelaFX的回答 - 知乎 https://www.zhihu.com/question/52900051/answer/132583244

这里R大主要就CLR上几种调优方式和为什么CLR不需要xmx、xmn等参数给出了原因

因为题主您就是没听说过 >_<

假定题主说的是下面三个层面的调优的头两种情况:

  1. 对VM的配置参数调优(例如GC参数)

  2. 对应用程序自身的代码调优

  3. 对VM自身的实现调优

(2)的话无论什么语言什么环境都好,追求性能的人肯定都有在做。Java和.NET都有好用的profiler可以帮助这方面的调查和调优。

有时候参数调优还不够的地方,也只能自己改自己的应用代码来解决问题了。请看一个经典案例:

In managed code we trust, our recent battles with the .NET Garbage Collector

(3)的话,CLR还没开源的时候,也无从调起。倒是有不少人给Mono贡献改进性能的patch,也算是广义上“.NET”的VM实现层面调优吧。

在CoreCLR开源后,也有不少人给CoreCLR贡献各种patch呢,包括“调优”。

.NET码农们以前时不时会中招的一种地方是程序进入GC的耗时(time-to-GC),也就是从CLR说“我要开始做GC了”到“真正开始做GC”之间的耗时。这里主要开销来自请求所有应用线程暂停(SuspendEE),这些线程要多久才完成对该请求的响应。听说过这个过程中会发生“250ms的倍数的等待时间”不?请跳传送门:

Garbage Collection Thread Suspension Delay (250ms Multiples)

像这种问题就是不进到VM内部做修改的话无法解决的。

(1)的话,其实就算当年CLR还没开源的时候,CLR也是有调优参数可以配置的呢。

最经典的就是选择试用Workstation GC(WKS GC)或者Server GC(SVR GC)。见过<gcServer>参数不?

后来可以配置使用Concurrent GC、Background Workstation GC、Background Server GC等。

用户还可以在代码里通过 GCSettings.LatencyMode 属性来影响GC的行为。

看,调优参数列表之一:
Runtime Settings Schema
不过CLR跟HotSpot VM在配置上有一个显著的区别,就是CLR不需要用户指定一个“GC堆的最大大小”。这跟CLR的GC堆的基础设计思路有关系。

HotSpot VM的GC堆一定要使用连续的虚拟地址空间。VM在启动的时候会一口气reserve GC所需要的整个地址空间,然后再按需commit。-Xmx会参与到GC堆最大大小的计算中。

CLR的GC堆则是分段式的(segemented),GC堆所用的空间会一个个segment分配,用满了一个再去分配一个新的;segment不需要在连续的地址空间上。这样GC堆可以按需自动增长或者缩减,可以一直增长到耗尽虚拟地址空间或者达到配额。

CLR这种分段式GC堆的好处是,在Windows上,特别是32位Windows上,虚拟地址空间中用户程序可以用的部分是比较零碎的,想要用到尽就不能对“连续的地址空间”有太多要求,这种条件下CLR跑在Windows上就可以充分利用资源。

而且这样一来,用户就不用头疼实现想好要配置多大的堆给CLR用了。反正它需要用多少会自己去增长。这用户体验就比绞尽脑汁想个好-Xmx要爽。

这种做法的坏处…怎能没有坏处呢。坏处也有若干。其中一个就是在这样的堆上实现的分代式GC的write barrier效率会比HotSpot那种用连续地址空间的要差一些。而且segmented heap实现起来也稍微复杂一些。

CLR 相比 JVM有哪些先进之处?

CLR 相比 JVM有哪些先进之处?- RednaxelaFX的回答 - 知乎 https://www.zhihu.com/question/39400401/answer/81293750

这里R大主要介绍了下CLR和JVM的不同,和下面hez大佬的回答可以对应起来

虽然只写了一半但还是先发出来免得坑掉。后面边讨论边更新吧…

这个问题原文是:

CLR 相比 JVM有哪些先进之处?

留下备份。

首先这个问题按其原样无法回答,因为CLR与JVM不是可比较的对象。

CLR(Common Language Runtime)是CLI(Common Language Infrastructure)规范中的VES(Virtual Execution System)的一种具体实现,而“JVM”不指定实现的话只能说是一种抽象的规范。

适合比较的对象是:

  • 规范层面:CLI vs JVM

  • 实现层面:CLR / Mono 等 vs HotSpot VM / J9 VM / JRockit VM 等

从规范层面看的话,CLI规范

ECMA-335

当前最新的版本是2012年出的第6版。我没太跟进新的CLI规范所以不确定这个版本的CLI与哪个版本的.NET Framework里的CLR对应。

JVM规范

The Java® Virtual Machine Specification

当前最新的版本则是2015年出的Java SE 8版。

在规范层面上,当前的CLI完胜当前的JVM。

《Virtual Machines: Versatile Platforms for Systems and Processes》

一书中有一章专门对比介绍了CLI与JVM的设计,值得一读。

JVM规范由Sun最初的JVM实现(后来称为Classic VM)抽象而来,然后几乎没有大的改动。后来的更新主要添加了Class文件对泛型信息的有限记录、注解(annotation)支持、字节码校验器的更新(split verifier / type checking verifier)、invokedynamic及MethodHandle支持、default method支持等。

最初的JVM规范虽然也提到它“可以支持多种语言”,但主要目的还是支持Java一种语言的执行,直到Java 7添加了JSR 292(invokedynamic与MethodHandle)后才有了专门为Java以外的语言设计的功能。

CLI由.NET最初的CLR实现抽象而来,然后与CLR一起逐渐进化。它出现的时间毕竟比JVM规范晚许多,而且一开始就以支持多种语言、多种范型的执行与互操作为设计目的,自然设计得更完善。对历史有兴趣的同学可以搜搜“Project 7”看。

Interviewer: I've heard that there was a project where Microsoft started to inte...

Don Syme: That's a small part of the sequence. The visional design of the .NET platform was very much expected to be a multi-language platform from the start. Right back in 1998, just in fact as our research group in programming languages started at Microsoft and I joined the team and then other 10 of us joined the team, we were approached by a guy called James Plamondon, who started the project called Project 7, which was about getting 7 academic and 7 industrial programming languages on each side to target the .NET common language runtime and really check out if it was good enough, to see if design changes could be made early on in the design process of .NET to make sure it was good enough for a range of programming languages.

Project 7的参与方尝试了将许多种语言移植到CLR上,包括C、Pascal、Cobol (Fujitsu)、Fortran (Salford)、Haskell、Standard ML、Eiffel、Active Oberon for .NET (ETH)、Gardens Point Component Pascal (QUT)等等。

后来还有更进一步的“Project 7+”。

Technical Overview of the Common Language Runtime

要追寻CLR更早的黑历史就不得不提微软的Visual J++。请跳传送门:

微软当年的 J++ 究竟是什么?为什么 Sun 要告它?- RednaxelaFX 的回答

下面先列举一些点提醒我回头更新…

Assembly vs Class文件

  • 常量池以stream的方式存在

  • 可以有strong name

CIL(Common Intermediate Language) / MSIL vs Java字节码

  • CIL不仅有二进制形式的规范,而且还有标准的文本形式语法;Java字节码只有二进制形式的规范

  • 局部变量区里无论什么类型的值都使用1个slot,而JVM则是long和double用相邻的2个slot

  • 异常处理支持filter

  • 支持具现化泛型(reified generics)

    • OpenJDK: Valhalla

  • 泛型支持声明点协变/逆变(declaration-site variance)

    • Java语言层面的泛型则是支持使用点协变/逆变(use-site variance)

  • 支持无符号整数类型(unsigned)

  • 支持用户自定义值类型(value type)

    • OpenJDK: Valhalla

  • 支持对用户自定义值类型指定显式内存布局,可以模拟C的struct和union以便互操作(StructLayout)

    • OpenJDK: Panama

  • 支持检查溢出的算术运算(checked arithmetic)

  • 支持有保证的尾调用(tail call)

  • 支持unsafe verifiable代码

  • 支持轻量代码生成(LCG,Lightweight Code Generation)

  • 支持委托类型(Delegate / MulticastDelegate)

  • CLI Delegate的single cast版本与Java 7的MethodHandle有相似之处

  • 支持方便的P/Invoke和Reverse P/Invoke

    • OpenJDK: Panama

  • 不支持自定义类加载器(custom class loader)。JVM上过于灵活的ClassLoader简直是头疼的要命,不支持这个简直好。

CLI里藏的私货:Assembly采用PE(Portable Executable)格式。PE是Windows上原生的可执行文件格式。

CLR与Windows的整合

  • Windows Loader可以直接识别.NET Assembly并启动CLR来执行程序。

  • Windows对GAC(Global Assembly Cache)有文件系统层面的特殊处理,“Fusion”。

  • 与COM有良好的互操作能力。毕竟CLR原本就是希望设计成下一代COM,原本还用过COR这个名字(COM Object Runtime)。

  • 分块式GC堆(Chunked GC Heap),可以自动扩张和收缩GC堆的大小,并且在Windows这种地址空间比较破碎的环境中可以有效的利用地址空间里的空隙。对应的,JRockit在Windows上则是用filler object来利用空隙。

  • GC堆分为多个空间,特别是高频堆/低频堆(high-frequency heap / low-frequency heap)的划分很有趣。

  • GC支持固定住对象(Object Pinning)

  • GC提供API让应用程序可以指定native对象的内存压力,以便GC与native协调工作(System.GC.AddMemoryPressure Method (Int64))

  • 支持Windows的结构化异常处理(SEH)。

CLR 与 一些JVM实现之间有对应物的

  • CLR:DAC / SOS扩展;HotSpot VM:Serviceability Agent;J9 VM:DTFJ / jdmpview

  • CLR:CAS(Code Access Security)与 JVM的沙箱

hez大佬的回答

再来给大家介绍一下hez2010大佬,今年刚从中山大学毕业,对于C++、.NET、C#、Rust等平台语言都有深入的研究,经常在博客园看文章的小伙伴应该早就看过hez佬的博文。他是.NET Runtime开源项目的持续贡献者、Microsoft Student Partner、可以说年少有为。

hez大佬的社交主页

个人博客:https://hez2010.com/
博客园:https://www.cnblogs.com/hez2010/
知乎:https://www.zhihu.com/people/hez2010
GitHub:https://github.com/hez2010

hez大佬回答相关问题摘抄

.NET Core已经开源好几年了, 为什么不像JVM那样很多人研究和调优其GC算法?

hez2010的回答 - 知乎 https://www.zhihu.com/question/365482363/answer/2389471084

这和虚拟机(这里指 JVM 和 CoreCLR)本身的特性有关系,由于基础设施的不同造成开发人员解决问题的取向不同。

当开发者遇到 GC 导致的问题时:

Java 开发者选择调优 GC,例如设置堆大小、调整各代和 region 的预算等等,最终使得“满足 GC 触发的条件”变得不那么容易满足来缓解这个问题,代价自然是内存占用更高,毕竟只要内存是无限的那就不需要 GC,同理只要 GC 对堆大小容忍度够高不去回收或者少回收,自然就能减轻 GC 带来的问题。因此开发者需要根据自身的 workload 来调配这些参数,最终达到一个既不会占用大的离谱甚至导致 OOM 错误,又不会导致频繁 GC 的平衡点。

而 .NET 开发者则会选择优化自己的代码,既然热路径中对象在托管堆内存上大量分配造成了频繁的 GC 导致出了性能问题,那干脆不用 class,转而去用 struct、stackalloc、fixed buffer、NativeMemory、Span 甚至指针,小对象什么的全都在栈上分配,用完自动随着栈的销毁而销毁,甚至 JIT 可以直接把小值类型对象优化到寄存器里面,连内存分配都不需要;堆内存也不需要 GC 托管堆了,直接用 NativeMemory 自己分配自己回收管理,全程完全不需要 GC 介入。这么做的指导思想很简单,既然是 GC 导致的问题,那么直接从源头解决:不分配托管堆内存就不需要 GC。

由于 CoreCLR 从一开始就是支持值类型、指针和非托管堆的,因此有能力的开发者可以在需要低延时的场景中(例如游戏)选择局部自行管理内存从而无需 GC;而其他大多数情况下 GC 并不会导致问题,因此这些时候开发者也可以充分利用 GC 带来的便利提升开发效率。

而 JVM 并没有这样的设施,因此开发者需要将解决问题的方法聚焦到如何让 GC 适应自己的 workload 上,通过调优一系列的参数来缓解因为 GC 导致的问题,再有就是通过 JVM 团队改进 GC 的算法来尽可能让 GC 暂停线程的时间变短。

另外,这也使得 JVM 和 CoreCLR 的工作重心完全不同,在 CoreCLR 上一个软实时 GC(ZGC)的重要性远远没有 JVM 上来的高,因此优先级就会变低。在 JVM 上 ZGC 是理所当然的重要,而在 CoreCLR 上却并不是,相反,.NET 工作重心则聚焦在改进 struct 相关的底层代码编写体验上:例如允许栈对象(ref struct)持有其他栈对象的引用(ref field),允许 ref struct 作泛型参数和约束,允许在栈上分配任何对象,以及栈对象生命周期的管理等等。

不过最近 CoreCLR 的 GC 团队也逐渐开始有兴趣实现软实时 GC 以改进游戏等低延时场景的开发体验(注意我说的是开发体验,因为让 GC 全盘管理堆内存可以很大程度上提升开发效率并避免内存安全问题,只是单纯要求低延时甚至 0 延时的话现在完全可以通过绕开 GC 做到),这也是建立在其他高优先级工作(例如 region 改造和 DPAD 等)基本都完成的基础上才轮到的。

至于某些极端情况,例如要求可预测的性能、绝对 0 GC 延时的,唯一办法只有绕开 GC,这种情况即使 ZGC 也无法对应。

更新:

补充一下,.NET 的 GC 是可以直接替换实现的,通过设置环境变量 DOTNET_GCName 指向你按照接口自己实现的 GC 的路径,就能做到替换掉自带的 GC:

https://docs.microsoft.com/en-us/dotnet/core/runtime-config/garbage-collector#standalone-gcdocs.microsoft.com/en-us/dotnet/core/runtime-config/garbage-collector#standalone-gc

所以要是真的对自带 GC 不满的话,可以考虑自己写 GC 来用。

总结

两位大佬回答的比较好,基本原因给说的比较明白了,在我看来两者的比较如下:

  • 从大多数人所认为“调优”选项来说,其实.NET CLR GC也是有调优选项的,只是因为CLR的GC默认使用了Segment方式来组织内存,会动态的申请和归还内存空间,所以不需要像JVM一些GC一样去人为的设置-xmx-xmn-xms这些选项。

  • 现在的.NET的GC和JVM上的GC(指G1)其实是平分秋色,因为都是为高吞吐量设计的分代并行GC,在高吞吐量下都有着不错的表现,当然各自也有优化空间。

  • 受制于JVM平台没有自定义值类型、stackalloc、NativeMemory、Span和指针等特性,.NET这边能无分配或者栈上分配地方JVM上需要堆分配。所以JVM平台上的GC压力会比CLR上的压力更大一些(虽然有逃逸分析、标量替换等等JIT辅助技术,但是没有原生那么快)。

  • JVM平台开源的比较早,所以它的GC有非常多的选择,虽然造成初学者面临很多调优和选择的问题,但是GC的丰富性这一点是.NET平台上所缺失的。

  • JVM平台上有单独低延时的C4和ZGC。目前.NET平台上没有单独低延时GC实现,.NET平台这边低延时第一是调整GCMode为GCLatencyMode.SustainedLowLatency,另外通过值类型、ref、栈上分配、非托管操作还有在关键路径暂时关闭GC等方式来实现低延时。

GC算法从提出到现在历经了几十年的时间,笔者也关注了一些近年的论文,其实总得来说在冯诺依曼架构体系下,GC垃圾回收算法已经没有颠覆性的变化。

在这个算力没有指数级增长的时代,各个语言的GC算法都开始趋同(C# Java Js Go等等),在没有更创新性的GC算法出来之前,从源头上避免分配和Rust语言那样的RAII管理内存可能是各个语言后面都会走的路。

如果大家想了解更多GC相关的知识,可以看下方的文章链接和推荐的书。

https://www.cnblogs.com/InCerry/p/dotnet-gc-workflow-1.html
https://www.cnblogs.com/InCerry/p/maoni-mem-doc.html
https://www.cnblogs.com/InCerry/p/put-a-dpad-on-that-gc.html

9bac057c414d3a2611a3863269e6f05f.png

9a511668a643d09932f45baf8cb18d97.png

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

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

相关文章

Ubuntu16.04 - 安装RabbitVCS,linux下的TortoiseSVN!!!

RabbitVCS 官网&#xff1a;http://rabbitvcs.org/ 1&#xff0c;添加PPA源。在shell里面执行下面命令&#xff1a; sudo add-apt-repository ppa:rabbitvcs/ppa 这个命令执行完毕后&#xff0c;查看执行结果看是否密钥导入成功&#xff0c;成功截图&#xff1a; 如果导入密钥失…

【ArcGIS微课1000例】0047:制图表达(2)---河流渐变效果的实现

当我们在ArcMap中加载河流数据时,得到的效果往往如图所示,仅仅是表示河流位置的线要素,既无法真实地反映河流的实际情况,同时在出图的时候也远没有任何美化效果。 文章目录 1.创建制图表达2.添加几何效果3.使用制图规则4.使用制图表达属性覆盖警告:这些操作会对您的数据库…

1 句代码,搞定 ASP.NET Core 绑定多个源到同一个类

问题有群友希望将路由中的信息绑定到一个Dto对象中&#xff1a;public class DDDDDto {[FromRoute(Name "collectionId")]public Guid collectionId { get; set; }[BindProperty(Name "relativeUrl")]public string relativeUrl { get; set; } }这样就不用…

设置git自动补全功能(windows版本)

目录 下载 Git 的源代码 在目录中 git/contrib/completion/ 中找到 git-completion.bash 文件 将 git-completion.bash 文件改名为 .git-completion.bash 找到本机git安装目录 将.git-completion.bash文件复制到git安装目录下的etc文件夹 打开同目录下的 bash.bashrc 文件&…

[转]Java 18 还未用上,Java 19 最新两大特性曝光

铁打的 Java&#xff0c;流水的版本。 不久前&#xff0c;Java 18 才正式发布&#xff0c;遵循 Oracle 六个月发一版本的频率&#xff0c;Java 19 将在今年 9 月出炉。这不&#xff0c;还没等众多开发者用上 Java 18&#xff0c;关于 Java 19 最新的两个目标功能就被披露了出…

C# 值类型和引用类型讲解

要了解值类型和引用类型&#xff0c;我们首先要知道堆和栈的区别&#xff1a;① 栈是编译期间就分配好的内存空间&#xff0c;因此你的代码中必须就栈的大小有明确的定义&#xff1b;堆是程序运行期间动态分配的内存空间&#xff0c;你可以根据程序的运行情况确定要分配的堆内存…

【ArcGIS微课1000例】0048:制图表达(3)---水立方效果实现

本文讲解ArcGIS中水立方效果的实现过程(制图表达案例)。 文章目录 一、效果展示二、制作步骤1. 创建数据库及要素数据集2. 创建范围3. 创建随机点4. 创建泰森多边形5. 创建制图表达一、效果展示 基于制图表达的思想,可以容易实现多种形式的水立方效果,例如: 怎么实现的呢…

Java中this与super的区别

2019独角兽企业重金招聘Python工程师标准>>> this与super关键字在java中构造函数中的应用&#xff1a; ** super()函数 ** super()函数在子类构造函数中调用父类的构造函数时使用&#xff0c;而且必须要在构造函数的第一行&#xff0c;例如&#xff1a; class Ani…

EF选择Mysql数据源

EF添加ADO.NET实体模型处直接选择Mysql数据源 最近想到EF是连接多数据库的orm框架&#xff0c;于是就想测试下。查了一堆网上资料后&#xff0c;测试连接mysql成功。步骤如下&#xff1a; 1、在你项目Model层中nuget安装MySql.Data.Entity 如果没安装这个provider 就进行下面的…

JIRA简介及基本概念

目录 第一章 JIRA简介 1.1 什么是JIRA 1.2 JIRA的主要功能 1.3 JIRA的主要特点 1.3.1 JIRA的优点 1.3.2 JIRA的缺点 1.4 相关版本 第二章 JIRA的基本概念 2.1 JIRA 中涉及的角色 2.1.1 管理人员 2.1.2 项目管理者 2.1.3 开发人员 2.1.4 测试人员 2.2 问题 2.2.1…

CodeChef Chef and Churu [分块]

题意&#xff1a; 单点修改$a$ 询问$a$的区间和$f$的区间和 原来普通计算机是这道题改编的吧... 对$f$分块&#xff0c;预处理$c[i][j]$为块i中$a_j$出现几次&#xff0c;$O(NH(N))$&#xff0c;只要每个块差分加上然后扫一遍就行了不用树状数组之类的 修改&#xff0c;整块直接…

SkiaSharp 之 WPF 自绘 拖曳小球(案例版)

感谢各位大佬和粉丝的厚爱和关心( 催更)&#xff0c;我会再接再厉的&#xff0c;其实这也是督促自己的一种方式&#xff0c;非常感谢。刚写了一篇万字长文&#xff0c;自己也休养生息(低调发育)了一段时间&#xff0c;接下来来几个小案例。拖曳小球WPF的拖曳效果&#xff0c;基…

ABP学习资源整理

不同的编程语言都有构建Web Application的框架&#xff0c;比如C#中的ASP.NET Core和ABP&#xff0c;Java中的Spring Boot和Spring Cloud&#xff0c;Python中的Django和Flask&#xff0c;Node.js中的Express和Koa2&#xff0c;Go中的Beego和Gin等。今天要介绍的主角是ABP框架&…

【ArcGIS微课1000例】0049:制图表达(4)---自由式制图表达

文章目录 一、转换为自由表达并编辑二、将效果转换为几何当编辑地图时,可能会遇到一个独特的或显著的特征,需要专门的符号的情况,可以使用覆盖的制图表达来实现,但是往往不够。可能需要简单地绘制一个图形以达到要求的外观,这时可以尝试使用自由式制图表达。 自由式制图表…

基于FPGA的异步FIFO设计

今天要介绍的异步FIFO&#xff0c;可以有不同的读写时钟&#xff0c;即不同的时钟域。由于异步FIFO没有外部地址端口&#xff0c;因此内部采用读写指针并顺序读写&#xff0c;即先写进FIFO的数据先读取&#xff08;简称先进先出&#xff09;。这里的读写指针是异步的&#xff0…

EJB

Enterprise JavaBean,企业级javabean,是J2EE的一部分&#xff0c;定义了一个用于 开发基于组件的企业多重应用程序的标准。其特点包括网络服务支持和核心开发工具(SDK)。 是Java的核心代码&#xff0c;分别是会话Bean&#xff08;Session Bean&#xff09;&#xff0c;实体Be…

WinForm(一):开始一个WinForm程序

WinForm程序只能运行在Windows上&#xff0c;即使是基于.NET5&#xff0c;6&#xff0c;7也一样。因为WinForm的UI层对接的底层API是基于Windows的。用VisualStudio创建一个WinForm应用很简单&#xff0c;建议使用非.NET Framework版&#xff0c;因为.NET Framework微软渐渐不支…

【ArcGIS微课1000例】0050:Geodatabase属性域操作全解

文章目录 1. 属性域的创建2. 属性域的查看3. 属性域的删除与修改4. 属性域的关联地理数据库按照面向对象的模型存储地理信息,也可以将其非空间信息保存在表中。对于要素和表可以设置一些规则进行限制,对属性的约束称为属性域。 属性域是描述字段合法值的规则,是一种增强数据…

『JavaScript』核心

为什么80%的码农都做不了架构师&#xff1f;>>> 弱类型语言 JavaScript是一种弱类型的语言。变量可以根据所赋的值改变类型。原始类型之间也可以进行类型转换。其弱类型的物质为其带来了极大的灵活性。 注意&#xff1a;原始类型使用值传递&#xff0c;复合类型使用…

优酷VIP会员周卡只需7.5元,看《沉香如屑》用优酷视频

由杨紫、成毅主演的《沉香如屑》已上线7天。站内热度值已经破万&#xff0c;也拿下了4次日冠的好成绩。追优酷视频最新热剧不能没有优酷VIP会员啊&#xff0c;优酷的会员&#xff0c;价格算是最便宜的了&#xff0c;下面是幻海优品优酷VIP会员特价充值的价格。优酷VIP会员特价充…