标签 Java 下的文章

Java 不再是最受欢迎的三大编程语言之一

根据最新的 TIOBE 指数,现在的排名是:Python 排名第一,C 第二,C++ 第三,Java 第四。2001 年以来,TIOBE 指数历史上 C++ 第一次超过了 Java。C++ 的激增,部分原因可能要归功于 2020 年 12 月发布的 C++ 20 稳定版。但在其它排行榜和调查中,Java 的表现更好。比如 Slashdata 数据显示,Java 在过去两年中以全球开发者社区两倍的速度增长,在社区规模中排名第三,超过了 C/C++,仅次于 Python 和 JavaScript。

消息来源:The Register
老王点评:我觉得语言排行榜的每次变化,除了给我添加一些话题之外,没啥意义。

谷歌再次推迟淘汰 MV2 扩展

谷歌推行的 Manifest V3 浏览器扩展规范,相比 V2 扩展,新版本增加了很多有利于谷歌的限制,比如限制广告屏蔽扩展。谷歌 原计划 在明年 1 月淘汰 MV3 扩展,但 MV3 仍存在一些问题,导致一些扩展没法迁移。这一期限被延迟到明年 6 月后,谷歌再次宣布推迟淘汰 MV2 扩展,但没有确定具体时间,谷歌表示要在 2023 年 3 月前听取开发者的更多反馈。

消息来源:谷歌
老王点评:谷歌审慎的态度很好,但是其本质上还是希望推进 MV3 的实施。

Adobe 公开发布 PostScript 源代码

Adobe 公司成立之初,他们就着手设计一种打印机无关的排版语言 PostScript,并于 1984 年发布。PostScript 本质上是一种数字化的印刷系统,它提供了其他任何地方都无法提供的能力,如文字和图像可以随意缩放、旋转和移动。如今大多数打印机都直接依赖 PostScript 技术,或者通过从它发展出来的 PDF 技术。而在它诞生近 40 年后,Adobe 公司通过计算机历史博物馆首次公开了 PostScript 的源代码。

消息来源:计算机历史博物馆
老王点评:这是印刷史上的一个里程碑,只是我没想到使用这么广泛的系统,源代码现在才公开。

Quarkus 令你可以使用类似 Java 的技术开发无服务器的工作负载。

无服务器 Java 的研究始于函数 —— 就是按需求运行的一小段代码。这一阶段并没有持续很长时间。虽然在 1.0 阶段,基于虚拟机架构的函数使这种范式变得很流行,但它仍然有局限性,例如执行时间、协议和糟糕的本地开发体验,都不太理想,如下图所示。

开发者随后意识到,可以把同样的无服务器特性应用于微服务和 Linux 容器,带来的好处也是一样的。由此进入 1.5 阶段,在这个阶段,一些无服务器容器完全抽象化了 Kubernetes,通过 Knative 或其它位于它之上的抽象层来提供无服务器的体验。

在 2.0 阶段,无服务器开始处理更复杂的编排和集成模式,并结合某些层级的状态管理。更重要的是,开发者关注的是能否在旧的系统中使用熟悉的 Java 应用程序运行时来组合运行无服务器和非无服务器的工作负载。

The serverless Java journey

Java 开发者开始进行无服务器函数开发之前,第一步是要选择一种新的云原生 Java 框架,从而能够以快于传统单体应用程序的速度和较小的内存占用运行 Java 函数。这在各种基础设施环境中,包括物理服务器、虚拟机、多云或混合云环境中的容器,都是适用的。

开发者也有可能固执地选择 Spring 框架中的 Spring 云函数 来进行命令式和反应式函数的开发。Spring 也支持将 Java 函数部署到可安装的无服务器平台,比如 KubelessApache OpenWhiskFissionProject Riff。然而,人们担心 Spring 的启动慢、响应时间长以及内存占用大的问题。在诸如 Kubernetes 这种可扩展的容器环境中运行 Java 函数,这些问题可能会更严重。

Quarkus 是一个新推出的开源云原生 Java 框架,它有助于解决这些问题。它的作用是设计无服务器应用程序,以及编写运行于云基础设施(例如 Kubernetes)的云原生微服务。

Quarkus 重新审视了 Java,它使用了封闭的方法构建和运行 Java 程序。它把 Java 转变为一种可与 Go 相媲美的运行时。Quarkus 也包含 100 多种扩展功能,集成了企业级能力,例如数据库访问、无服务器集成、消息、安全、可观察性和业务自动化。

这里有一个简单例子,展现如何使用 Quarkus 创建一个 Java 无服务器项目的框架。

1、基于 Maven 创建一个 Quarkus 无服务器项目

安装一个本地 Kubernetes 集群,开发者有多种选择,包括 MinikubeOKD。因为使用 OKD 在 Knative 和 DevOps 工具上安装无服务器相关功能较方便,本文使用 OKD 安装集群。这些关于 OKD 安装Knative 操作员安装 的相关指南中提供了更多的设置资料。

下面的命令创建了一个 Quarkus 项目(例如 quarkus-serverless-restapi),对外暴露一个简单的 REST API,并下载 quarkus-openshift 扩展,用于 Knative 服务的部署:

$ mvn io.quarkus:quarkus-maven-plugin:1.13.4.Final:create \
       -DprojectGroupId=org.acme \
       -DprojectArtifactId=quarkus-serverless-restapi \
       -Dextensions="openshift" \
       -DclassName="org.acme.getting.started.GreetingResource"

2、在本地运行无服务器功能

使用 Quarkus 开发模式运行程序,检查 REST API 是否有效,稍稍调整一下代码:

$ ./mvnw quarkus:dev

输出如下内容:

__  ____  __  _____   ___  __ ____  ______ 
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ 
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \   
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/   
INFO  [io.quarkus] (Quarkus Main Thread) quarkus-serverless-restapi 1.0.0-SNAPSHOT on JVM (powered by Quarkus xx.xx.xx.) started in 2.386s. Listening on: http://localhost:8080
INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, kubernetes, resteasy]
注意: 保持 Quarkus 应用程序运行,需要使用 热部署 Live Coding 。这样,当代码修改后,你就不必重新构建、重新部署以及重启运行时。

现在,你可以使用一个 curl 命令快速访问 REST API。输出结果应当是 Hello RESTEasy:

$ curl localhost:8080/hello
Hello RESTEasy

GreetingResource.java 中修改返回值:

public String hello() {
        return "Quarkus Function on Kubernetes";
    }

再次访问 REST API,输出信息也会相应更新:

$ curl localhost:8080/hello
Quarkus Function on Kubernetes

普通的微服务跟无服务器函数之间的差别并不大。使用 Quarkus 的好处在于:开发者可以使用任何微服务,将 Kubernetes 部署为无服务器函数。

3、在 Knative 服务中部署相关的函数

如果你还没有创建命名空间,就在你的 OKD 集群上 创建命名空间(例如 quarkus-serverless-restapi),用来部署 Java 无服务器函数。

Quarkus 令开发者可以通过在 src/main/resources/application.properties 中添加以下变量,创建 Knative 和 Kubernetes 资源:

quarkus.container-image.group=quarkus-serverless-restapi <1>
quarkus.container-image.registry=image-registry.openshift-image-registry.svc:5000 <2>
quarkus.kubernetes-client.trust-certs=true <3>
quarkus.kubernetes.deployment-target=knative <4>
quarkus.kubernetes.deploy=true <5>
quarkus.openshift.build-strategy=docker <6>

说明:

  • <1> 在你部署无服务器应用程序的位置定义项目名
  • <2> 使用容器注册中心
  • <3> 在这个简单例子中,使用自签名证书,以便通过相关信任机制
  • <4> 允许创建 Knative 资源
  • <5> 指示在构建容器映像之后将扩展部署到 OpenShift
  • <6> 设置 Docker 构建策略

执行以下命令,构建应用程序,并直接部署到 OKD 集群:

$ ./mvnw clean package -DskipTests
注意: 应该提前使用 oc login 命令,确保登录到正确的项目(例如quarkus-serverless-restapi)。

输出结果应该以 BUILD SUCCESS 结束。

在对于 Knative 服务执行的 oc 命令中,加上标签:

$ oc label rev/quarkus-serverless-restapi-00001 
app.openshift.io/runtime=quarkus --overwrite

然后访问 OKD 网页控制台,就能进入 开发人员透视图中的拓扑视图。你可能会看到你的 容器荚 Pod (无服务器函数)已经缩小为零(白线圈)。

Topology view

4、在 Kubernetes 环境下测试函数

运行如下 oc 命令,搜索含有无服务器函数的路由:

$ oc get rt/quarkus-serverless-restapi
[...]
NAME                      URL                             READY   REASON
quarkus-serverless[...]   http://quarkus[...].SUBDOMAIN   True

使用 curl 命令访问搜索到的路由:

$ curl http://quarkus-serverless-restapi-quarkus-serverless-restapi.SUBDOMAIN/hello

过几秒钟,你可以得到跟在本地相同的结果:

Quarkus Function on Kubernetes

当你回到 OKD 集群内的拓扑图,Knative 服务会自动扩展。

Scaling the Knative Function

由于 Knative 服务的默认设置,其 pod 在 30 秒后会再次下降至零。

下一步呢?

无服务器不断地在演变,始于运行于虚拟机的函数,到后来的无服务器容器,并与企业原有系统集成。在此过程中,企业开发者借助 Quarkus,仍然可以使用自己熟悉的技术(比如 Java)创建一个项目,然后构建并部署到 Kubernetes。

本系列的下一篇文章将指导你优化 Kubernetes 中的 Java 无服务器函数,从而令程序启动更快,内存占用更小。

文内图像来自:Daniel Oh, CC BY-SA 4.0


via: https://opensource.com/article/21/6/java-serverless-functions

作者:Daniel Oh 选题:lkxed 译者:cool-summer-021 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

安装 Java,使用 Maven 安装 JDBC,并安装数据库。然后,你就可以在 Java 代码中与数据库进行交互了。

当你编写一个应用时,需要数据存储是很常见的。有时你要存储你的应用需要的素材数据,其他时候你要存储用户数据,包括偏好和保存的数据。存储数据的一种方式是在数据库中,为了在你的代码和数据库之间进行通信,你需要为你的语言提供一个数据库绑定或连接器。对于 Java 来说,一个常见的数据库连接器是 JDBC( Java 数据库连接 Java database connectivity )。

1、安装 Java

当然,要使用 Java 进行开发,你还必须安装 Java。对于 Linux、macOS 和 WSL 或 Cygwin,我推荐 SDKman。对于 Windows,你可以从 developers.redhat.com 下载 OpenJDK。

2、使用 Maven 安装 JDBC

JDBC 是一种 API,通过语句 import java.sql.* 导入到你的代码中,但要使其有用,你必须安装数据库驱动和数据库以与之交互。你使用的数据库驱动和要通信的数据库必须匹配:要与 MySQL 交互,你需要 MySQL 驱动,要与 SQLite3 交互,你必须具有 SQLite3 驱动等等。

在本文中,我使用 PostgreSQL,但所有主流数据库,包括 MariaDBSQLite3,都有 JDBC 驱动程序。

你可以从 jdbc.postgresql.org 下载 JDBC for PostgreSQL。我使用 Maven 来管理 Java 依赖项,因此我将它包含在 pom.xml 中(调整 Maven Central 上的当前版本号):

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.5.0</version>
</dependency>

3、安装数据库

你必须安装要通过 JDBC 连接的数据库。有几个非常好的开源数据库,但是我只能为这篇文章选择一个,所以我选择了 PostgreSQL。

要在 Linux 上安装 PostgreSQL,请使用你的软件仓库。在 Fedora、CentOS、Mageia 和类似设备上:

$ sudo dnf install postgresql postgresql-server

在 Debian、Linux Mint、Elementary 和类似平台上:

$ sudo apt install postgresql postgresql-contrib

数据库连接

如果你不使用 PostgreSQL,同样的一般过程也适用:

  1. 安装 Java。
  2. 为你选择的数据库找到 JDBC 驱动,并将其包含在你的 pom.xml 文件中。
  3. 在你的开发系统上安装数据库(服务器和客户端)。

三个步骤,你就可以开始编写代码了。


via: https://opensource.com/article/22/9/install-jdbc-linux

作者:Seth Kenlon 选题:lkxed 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

了解 Java 中的内存管理。

用 C 或 C++ 这样的编程语言写一个应用时,需要编写代码来销毁内存中不再需要的对象。当应用程序扩展得越来越复杂时,未使用对象被忽略释放的可能性就越大。这会导致内存泄露,最终内存耗尽,在某个时刻将没有更多的内存可以分配。结果就是应用程序运行失败并出现 OutOfMemoryError 错误。但在 Java 中, 垃圾收集器 Garbage Collection (GC)会在程序执行过程中自动运行,减轻了手动分配内存和可能的内存泄漏的任务。

垃圾收集器并不只有一种,Java 虚拟机(JVM)有七种不同的垃圾收集器,了解每种垃圾收集器的目的和优点是很有用的。

1、Serial 收集器

Serial threaded garbage collection

垃圾收集器的原始实现,使用单线程。当垃圾收集器运行时,会停止应用程序(通常称为“stop the world”事件)。适用于能够承受短暂停顿的应用程序。该垃圾收集器占用内存空间比较小,因此这是嵌入式应用程序的首选垃圾收集器类型。在运行时使用以下命令启用该垃圾收集器:

$ java -XX:+UseSerialGC

2、Parallel 收集器

Parallel garbage collection

像 Serial 收集器一样,Parallel 收集器也使用“stop the world”方法。这意味着,当垃圾收集器运行时,应用程序线程会停止。但是不同的是,Parallel 收集器运行时有多个线程执行垃圾收集操作。这种类型的垃圾收集器适用于在多线程和多处理器环境中运行中到大型数据集的应用程序。

这是 JVM 中的默认垃圾收集器,也被称为吞吐量收集器。使用该垃圾收集器时可以通过使用各种合适的 JVM 参数进行调优,例如吞吐量、暂停时间、线程数和内存占用。如下:

  • 线程数:-XX:ParallelGCThreads=<N>
  • 暂停时间:-XX:MaxGCPauseMillis=<N>
  • 吞吐量(垃圾收集花费的时间与实际应用程序执行的时间相比):-XX:GCTimeRatio=<N>
  • 最大堆内存:-Xmx<N>

Parallel 收集器可以使用该命令显式启用:java -XX:+UseParallelGC 。使用这个命令,指定在新生代中通过多个线程进行垃圾回收,而老年代中的垃圾收集和内存压缩仍使用单个线程完成的。

还有一个版本的的 Parallel 收集器叫做 “Parallel Old GC”,它对新生代和老年代都使用多线程,启用命令如下:

$ java -XX:+UseParallelOldGC

3、Concurrent Mark Sweep(CMS)收集器

Concurrent garbage collection

Concurrent Mark Sweep(CMS)垃圾收集器与应用程序并行运行。对于新生代和老年代都使用了多线程。在 CMS 垃圾收集器删除无用对象后,不会对存活对象进行内存压缩。该垃圾收集器和应用程序并行运行,会降低应用程序的响应时间,适用于停顿时间较短的应用程序。这个收集器在 Java8 已过时,并在 Java14 中被移除。如果你仍在使用有这个垃圾收集器的 Java 版本,可以使用如下命令启用:

$ java -XX:+UseConcMarkSweepGC

在 CMS 垃圾收集器使用过程中,应用程序将暂停两次。首次暂停发生在标记可直接访问的存活对象时,这个暂停被称为初始标记。第二次暂停发生在 CMS 收集器结束时期,来修正在并发标记过程中,应用程序线程在 CMS 垃圾回收完成后更新对象时被遗漏的对象。这就是所谓的重新标记

4、G1 收集器

Garbage first

G1 垃圾收集器旨在替代 GMS。G1 垃圾收集器具备并行、并发以及增量压缩,且暂停时间较短。与 CMS 收集器使用的内存布局不同,G1 收集器将堆内存划分为大小相同的区域,通过多个线程触发全局标记阶段。标记阶段完成后,G1 知道哪个区域可能大部分是空的,并首选该区域作为清除/删除阶段。

在 G1 收集器中,一个对象如果大小超过半个区域容量会被认为是一个“大对象” 。这些对象被放置在老年代中,在一个被称为“humongous region”的区域中。 启用 G1 收集器的命令如下:

$ java -XX:+UseG1GC

5、Epsilon 收集器

该垃圾收集器是在 Java11 中引入的,是一个 no-op(无操作)收集器。它不做任何实际的内存回收,只负责管理内存分配。Epsilon 只在当你知道应用程序的确切内存占用情况并且不需要垃圾回收时使用。启用命令如下:

$ java -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC

6、Shenandoah 收集器

Shenandoah 是在 JDK12 中引入的,是一种 CPU 密集型垃圾收集器。它会进行内存压缩,立即删除无用对象并释放操作系统的空间。所有的这一切与应用程序线程并行发生。启用命令如下:

$ java -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC

7、ZGC 收集器

ZGC 为低延迟需要和大量堆空间使用而设计,允许当垃圾回收器运行时 Java 应用程序继续运行。ZGC 收集器在 JDK11 引入,在 JDK12 改进。在 JDK15,ZGC 和 Shenandoah 都被移出了实验阶段。启用 ZGC 收集器使用如下命令:

$ java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC

灵活的垃圾收集器

Java 为我们提供了灵活的内存管理方式,熟悉不同的可用方法有助于为正在开发或运行的应用程序选择最合适的内存管理方式。


via: https://opensource.com/article/22/7/garbage-collection-java

作者:Jayashree Huttanagoudar 选题:lkxed 译者:Veryzzj 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

对于程序员来说,掌握 Java 的内存管理机制并不是必须的,但它能够帮助你更好地理解 JVM 是如何处理程序中的变量和类实例的。

Java 之所以能够如此流行,自动 垃圾回收 Garbage Collection (GC)功不可没,它也是 Java 最重要的几个特性之一。在这篇文章中,我将说明为什么垃圾回收如此重要。本文的主要内容为:自动的分代垃圾回收、JVM 划分内存的依据,以及 JVM 垃圾回收的工作原理。

Java 内存分配

Java 程序的内存空间被划分为以下四个区域:

  1. 堆区 Heap :对象实例就是在这个区域分配的。不过,当我们声明一个对象时,堆中不会发生任何内存分配,只是在栈中创建了一个对象的引用而已。
  2. 栈区 Stack :方法、局部变量和类的实例变量就是在这个区域分配的。
  3. 代码区 Code :这个区域存放了程序的字节码。
  4. 静态区 Static :这个区域存放了程序的静态数据和静态方法。

什么是自动垃圾回收?

自动垃圾回收是这样一个过程:首先,堆中的所有对象会被分类为“被引用的”和“未被引用的”;接着,“未被引用的对象”就会被做上标记,以待之后删除。其中,“被引用的对象”是指程序中的某一部分仍在使用的对象,“未被引用的对象”是指目前没有正在被使用的对象。

许多编程语言,例如 C 和 C++,都需要程序员手动管理内存的分配和释放。在 Java 中,这一过程是通过垃圾回收机制来自动完成的(尽管你也可以在代码中调用 system.gc(); 来手动触发垃圾回收)。

垃圾回收的基本步骤如下:

1、标记已使用和未使用的对象

在这一步骤中,已使用和未使用的对象会被分别做上标记。这是一个及其耗时的过程,因为需要扫描内存中的所有对象,才能够确定它们是否正在被使用。

标记已使用和未使用的对象

2、扫描/删除对象

有两种不同的扫描和删除算法:

简单删除(标记清除):它的过程很简单,我们只需要删除未被引用的对象即可。但是,后续给新对象分配内存就会变得很困难了,因为可用空间被分割成了一块块碎片。

标记清除的过程

删除压缩(标记整理):除了会删除未被引用的对象,我们还会压缩被引用的对象(未被删除的对象)。这样以来,新对象的内存分配就相对容易了,并且内存分配的效率也有了提升。

标记整理的过程

什么是分代垃圾回收,为什么需要它?

正如我们在“扫描删除”模型中所看到的,一旦对象不断增长,我们就很难扫描所有未使用的对象以回收内存。不过,有一项实验性研究指出,在程序执行期间创建的大多数对象,它们的存活时间都很短。

既然大多数对象的存活时间都很短,那么我们就可以利用这个事实,从而提升垃圾回收的效率。该怎么做呢?首先,JVM 将内存划分为不同的“代”。接着,它将所有的对象都分类到这些内存“代”中,然后对这些“代”分别执行垃圾回收。这就是“分代垃圾回收”。

堆内存的“代”和分代垃圾回收过程

为了提升垃圾回收中的“标记清除”的效率,JVM 将对内存划分成以下三个“代”:

  • 新生代 Young Generation
  • 老年代 Old Generation
  • 永久代 Permanent Generation

Hotspot 堆内存结构

下面我将介绍每个“代”及其主要特征。

新生代

所有创建不久的对象都存放在这里。新生代被进一步分为以下两个区域:

  1. 伊甸区 Eden :所有新创建的对象都在此处分配内存。
  2. 幸存者区 Survivor ,分为 S0 和 S1:经历过一次垃圾回收后,仍然存活的对象会被移动到两个幸存者区中的一个。

对象分配

在新生代发生的分代垃圾回收被称为 “ 次要回收 Minor GC ”(LCTT 译注:也称为“ 新生代回收 Young GC ”)。Minor GC 过程中的每个阶段都是“ 停止世界 Stop The World ”(STW)的,这会导致其他应用程序暂停运行,直到垃圾回收结束。这也是次要回收更快的原因。

一句话总结:伊甸区存放了所有新创建的对象,当它的可用空间被耗尽,第一次垃圾回收就会被触发。

填充伊甸区

次要回收:在该垃圾回收过程中,所有存活和死亡的对象都会被做上标记。其中,存活对象会被移动到 S0 幸存者区。当所有存活对象都被移动到了 S0,未被引用的对象就会被删除。

拷贝被引用的对象

S0 中的对象年龄为 1,因为它们挺过了一次次要回收。此时,伊甸区和 S1 都是空的。

每当完成清理后,伊甸区就会再次接受新的存活对象。随着时间的推移,伊甸区和 S0 中的某些对象被宣判死亡(不再被引用),并且伊甸区的可用空间也再次耗尽(填满了),那么次要回收 又将再次被触发。

对象年龄增长

这一次,伊甸区和 S0 中的死亡和存活的对象会被做上标记。其中,伊甸区的存活对象会被移动到 S1,并且年龄增加至 1。S0 中的存活对象也会被移动到 S1,并且年龄增加至 2(因为它们挺过了两次次要回收)。此时,伊甸区和 S0 又是空的了。每次次要回收之后,伊甸区和两个幸存者区中的一个都会是空的。

新对象总是在伊甸区被创建,周而复始。当下一次垃圾回收发生时,伊甸区和 S1 都会被清理,它们中的存活对象会被移动到 S0 区。每次次要回收之后,这两个幸存者区(S0 和 S1)就会交换一次。

额外年龄增长

这个过程会一直进行下去,直到某个存活对象的年龄达到了某个阈值,然后它就会被移动到一个叫做“老年代”的地方,这是通过一个叫做“晋升”的过程来完成的。

使用 -Xmn 选项可以设置新生代的大小。

老年代

这个区域存放着那些挺过了许多次次要回收,并且达到了某个年龄阈值的对象。

晋升

在上面这个示例图表中,晋升的年龄阈值为 8。在老年代发生的垃圾回收被称为 “ 主要回收 Major GC ”。(LCTT 译注:也被称为“ 全回收 Full GC ”)

使用 -Xms-Xmx 选项可以分别设置堆内存大小的初始值和最大值。(LCTT 译注:结合上面的 -Xmn 选项,就可以间接设置老年代的大小了。)

永久代

永久代存放着一些元数据,它们与应用程序、Java 标准环境以及 JVM 自用的库类及其方法相关。JVM 会在运行时,用到了什么类和方法,就会填充相应的数据。当 JVM 发现有未使用的类,就会卸载或是回收它们,从而为正在使用的类腾出空间。

使用 -XX:PermGen-XX:MaxPerGen 选项可以分别设置永久代大小的初始值和最大值。

元空间

Java 8 引入了 元空间 Metaspace ,并用它替换了永久代。这么做的好处是自动调整大小,避免了 内存不足 OutOfMemory (OOM)错误。

总结

本文讨论了各种不同的 JVM 内存“代”,以及它们是如何在分代垃圾回收算法中起作用的。对于程序员来说,掌握 Java 的内存管理机制并不是必须的,但它能够帮助你更好地理解 JVM 处理程序中的变量和类实例的方式。这种理解使你能够规划和排除代码故障,并理解特定平台固有的潜在限制。

正文配图来自:Jayashree Huttanagoudar,CC BY-SA 4.0


via: https://opensource.com/article/22/6/garbage-collection-java-virtual-machine

作者:Jayashree Huttanagoudar 选题:lkxed 译者:lkxed 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

GNOME 专利巨魔被剥夺了专利

2019 年,RPI 声称 GNOME 项目的 Shotwell 软件侵犯了其专利。这促使 4000 多名自由开源软件社区的成员团结起来为 GNOME 基金会辩护,筹集了超过 15 万美元来抵御这一虚假的索赔。最终,GNOME 基金会与 RPI 达成和解,并为所有开源软件获得了全面和免费的专利许可。

但这不是故事的结尾,一位从事开源律师工作超过 20 年的律师 McCoy Smith,认为该专利是无效的,不应该被授予,于是对该专利发起无效复审。美国专利商标局同意该专利不是任何新发明。该专利不能在用来对付任何人,包括开源项目。

消息来源:opensource
老王点评:主动出击!干得漂亮!

报告称 Oracle Java 的受欢迎程度在下滑

根据应用监控公司 New Relic 的报告,虽然 Oracle Java 仍然是业界领先的 Java 发行版,但其受欢迎程度只有两年前的一半。该报告的数据基于向 New Relic 提供性能数据的数百万个应用程序。据报告,在 Java 发行版中,Oracle 公司在 2020 年约有 75% 的市场份额,但在 2022 年只有 34.48%。第二名是亚马逊,占 22.04%。

此外,该报告还显示 Java 11 是最流行的 Java 发行版,占据 48%;其次是 Java 8,占据 46.45%,2020 年它占据 84.48%。而非 LTS 版本的 Java 发行版份额很少。

消息来源:infoworld
老王点评:不管你喜欢不喜欢,Java 真是一直长青啊。

加密货币市场下跌 2000 亿美元,11 月以来比特币下跌 50%

大约三分之一的跌幅发生在本周,在短短几天内从加密货币市场上抹去了约 2000 亿美元。比特币现在处于自去年 7 月以来的最低价。就在 40 天前,比特币售价为 47454 美元。它现在的价格是 34000 美元,下降了 28%。现在比 2021 年 11 月的最高价格 67802.30 美元下跌了 50%。

消息来源:cnbc
老王点评:又是一波洗牌,炒币有风险。