跳转到主要内容

标签(标签)

资源精选(342) Go开发(108) Go语言(103) Go(99) angular(82) LLM(75) 大语言模型(63) 人工智能(53) 前端开发(50) LangChain(43) golang(43) 机器学习(39) Go工程师(38) Go程序员(38) Go开发者(36) React(33) Go基础(29) Python(24) Vue(22) Web开发(20) Web技术(19) 精选资源(19) 深度学习(19) Java(18) ChatGTP(17) Cookie(16) android(16) 前端框架(13) JavaScript(13) Next.js(12) 安卓(11) 聊天机器人(10) typescript(10) 资料精选(10) NLP(10) 第三方Cookie(9) Redwoodjs(9) LLMOps(9) Go语言中级开发(9) 自然语言处理(9) PostgreSQL(9) 区块链(9) mlops(9) 安全(9) 全栈开发(8) ChatGPT(8) OpenAI(8) Linux(8) AI(8) GraphQL(8) iOS(8) 软件架构(7) Go语言高级开发(7) AWS(7) C++(7) 数据科学(7) whisper(6) Prisma(6) 隐私保护(6) RAG(6) JSON(6) DevOps(6) 数据可视化(6) wasm(6) 计算机视觉(6) 算法(6) Rust(6) 微服务(6) 隐私沙盒(5) FedCM(5) 语音识别(5) Angular开发(5) 快速应用开发(5) 提示工程(5) Agent(5) LLaMA(5) 低代码开发(5) Go测试(5) gorm(5) REST API(5) 推荐系统(5) WebAssembly(5) GameDev(5) CMS(5) CSS(5) machine-learning(5) 机器人(5) 游戏开发(5) Blockchain(5) Web安全(5) Kotlin(5) 低代码平台(5) 机器学习资源(5) Go资源(5) Nodejs(5) PHP(5) Swift(5) 智能体(4) devin(4) Blitz(4) javascript框架(4) Redwood(4) GDPR(4) 生成式人工智能(4) Angular16(4) Alpaca(4) 编程语言(4) SAML(4) JWT(4) JSON处理(4) Go并发(4) kafka(4) 移动开发(4) 移动应用(4) security(4) 隐私(4) spring-boot(4) 物联网(4) nextjs(4) 网络安全(4) API(4) Ruby(4) 信息安全(4) flutter(4) 专家智能体(3) Chrome(3) CHIPS(3) 3PC(3) SSE(3) 人工智能软件工程师(3) LLM Agent(3) Remix(3) Ubuntu(3) GPT4All(3) 软件开发(3) 问答系统(3) 开发工具(3) 最佳实践(3) RxJS(3) SSR(3) Node.js(3) Dolly(3) 移动应用开发(3) 低代码(3) IAM(3) Web框架(3) CORS(3) 基准测试(3) Go语言数据库开发(3) Oauth2(3) 并发(3) 主题(3) Theme(3) earth(3) nginx(3) 软件工程(3) azure(3) keycloak(3) 生产力工具(3) gpt3(3) 工作流(3) C(3) jupyter(3) 认证(3) prometheus(3) GAN(3) Spring(3) 逆向工程(3) 应用安全(3) Docker(3) Django(3) R(3) .NET(3) 大数据(3) Hacking(3) 渗透测试(3) C++资源(3) Mac(3) 微信小程序(3) Python资源(3) JHipster(3) 大型语言模型(2) 语言模型(2) 可穿戴设备(2) JDK(2) SQL(2) Apache(2) Hashicorp Vault(2) Spring Cloud Vault(2) Go语言Web开发(2) Go测试工程师(2) WebSocket(2) 容器化(2) AES(2) 加密(2) 输入验证(2) ORM(2) Fiber(2) Postgres(2) Gorilla Mux(2) Go数据库开发(2) 模块(2) 泛型(2) 指针(2) HTTP(2) PostgreSQL开发(2) Vault(2) K8s(2) Spring boot(2) R语言(2) 深度学习资源(2) 半监督学习(2) semi-supervised-learning(2) architecture(2) 普罗米修斯(2) 嵌入模型(2) productivity(2) 编码(2) Qt(2) 前端(2) Rust语言(2) NeRF(2) 神经辐射场(2) 元宇宙(2) CPP(2) 数据分析(2) spark(2) 流处理(2) Ionic(2) 人体姿势估计(2) human-pose-estimation(2) 视频处理(2) deep-learning(2) kotlin语言(2) kotlin开发(2) burp(2) Chatbot(2) npm(2) quantum(2) OCR(2) 游戏(2) game(2) 内容管理系统(2) MySQL(2) python-books(2) pentest(2) opengl(2) IDE(2) 漏洞赏金(2) Web(2) 知识图谱(2) PyTorch(2) 数据库(2) reverse-engineering(2) 数据工程(2) swift开发(2) rest(2) robotics(2) ios-animation(2) 知识蒸馏(2) 安卓开发(2) nestjs(2) solidity(2) 爬虫(2) 面试(2) 容器(2) C++精选(2) 人工智能资源(2) Machine Learning(2) 备忘单(2) 编程书籍(2) angular资源(2) 速查表(2) cheatsheets(2) SecOps(2) mlops资源(2) R资源(2) DDD(2) 架构设计模式(2) 量化(2) Hacking资源(2) 强化学习(2) flask(2) 设计(2) 性能(2) Sysadmin(2) 系统管理员(2) Java资源(2) 机器学习精选(2) android资源(2) android-UI(2) Mac资源(2) iOS资源(2) Vue资源(2) flutter资源(2) JavaScript精选(2) JavaScript资源(2) Rust开发(2) deeplearning(2) RAD(2)

JDK8和以后的JDK版本之间进行了重大更改。

每一个新的JavaSE版本都引入了一些与以前版本的二进制、源代码和行为不兼容。JDK9中发生的Java SE平台的模块化以及后来的模块化带来了许多好处,但也带来了许多变化。只使用官方Java SE平台API和受支持的JDK特定API的代码应该可以继续工作而不会发生更改。使用JDK内部API的代码应该继续运行,但应该迁移以使用支持的API。

某些API在其默认行为中被设置为不可访问、删除或更改。编译或运行应用程序时可能会遇到问题。请参阅删除的工具和组件以及安全更新。

以下部分描述了JDK包中的更改,当您将JDK 8应用程序迁移到以后的JDK版本时,您应该注意这些更改。

查看运行应用程序时可能遇到的更改列表。

  • JDK中的强封装
  • 新版本字符串方案
  • 对已安装JDK/JJRE映像的更改
  • 部署
  • 垃圾收集的更改
  • 运行Java小程序
  • 正则表达式匹配中的行为变化
  • 安全管理器已弃用并删除

当您的应用程序在最新版本的JDK上成功运行时,请查看“下一步”,它将帮助您避免未来版本出现问题。

JDK中的强封装

一些工具和库使用反射来访问JDK中仅供内部使用的部分。这种反射的使用对JDK的安全性和可维护性产生了负面影响。为了帮助迁移,JDK9到JDK16允许这种反射继续进行,但发出了关于非法反射访问的警告。然而,JDK17是强封装的,因此默认情况下不再允许这种反射。访问java.*API的非公共字段和方法的代码将抛出InaccessibleObjectException。

请注意,sun.misc和sun.reflect包可供所有JDK版本(包括JDK17)中的工具和库反射。

java启动器选项——非法访问允许从JDK9到JDK16中的JDK内部反射。您可以指定以下参数:

  • --illegal-access=permit:允许类路径上的代码反映JDK8中存在的java.*包的内部。对任何这样的元件的第一次反射访问操作导致发出警告,但在该点之后不发出警告。
  • --illegal-access=warn:导致为每个非法反射访问操作发出警告消息。
  • --illegal-access=debug:导致为每个非法反射访问操作显示警告消息和堆栈跟踪。
  • --illegal-access=deny: 禁用所有非法的反射访问操作,但由其他命令行选项(如--add-opens)启用的操作除外。

许多工具和库已经更新,以避免依赖JDK内部,而是使用JDK8和17之间引入的标准Java API。这意味着--非法访问启动器选项在JDK17中已经过时。JDK17中使用此启动器选项,无论是许可、警告、调试还是拒绝,都不会产生任何效果,只会发出警告消息。

如果无法获取或部署较新版本的工具和库,则有两个命令行选项可用于授予对较旧版本工具和库的特定内部API的访问权限:

  • --add-exports: 如果您有一个较旧的工具或库需要使用经过强封装的内部API,请使用--add-expports运行时选项。您还可以在编译时使用--add导出来访问内部API。
  • --add-opens: 如果您有一个旧的工具或库需要通过反射访问java.*API的非公共字段和方法,那么请使用--add-open选项。

请参阅JEP 403:默认情况下强封装JDK内部。

--add-exports

如果有一个较旧的工具或库需要使用经过强封装的内部API,请使用--add-exports运行时选项。您还可以在编译时使用--add导出来访问内部API。

--add exports选项的语法为:

--add-exports <source-module>/<package>=<target-module>(,<target-module>)*

其中<source module>和<target module>是模块名称,<package>是包的名称。

如果目标模块读取源模块,那么--add exports选项允许目标模块中的代码访问源模块的命名包中的类型。

作为一种特殊情况,如果<目标模块>是ALL-UNNAMED,则源包将导出到所有未命名的模块,无论这些模块最初存在还是以后创建。例如:

 

--add-exports java.management/sun.management=ALL-UNNAMED

此示例允许所有未命名模块中的代码(类路径上的代码)访问java.management/sun.management中公共类型的公共成员。

注意:如果类路径上的代码使用反射API(setAccessible(true))试图访问java.*API的非公共字段和方法,那么代码将失败。JDK 17默认情况下不允许这样做。但是,您可以使用--add-opens选项来允许这样做。有关详细信息,请参阅“添加打开”一节。

如果在类路径上运行的应用程序oldApp必须使用java.management模块的未导出com.sun.jmx.remote.internal包,则可以通过以下方式授予其所需的访问权限:

复制

--add-exports java.management/com.sun.jmx.remote.internal=ALL-UNNAMED

您还可以使用AddExportsJAR文件清单属性:

复制

Add-Exports:java.management/sun.management

请小心使用--add exports选项。您可以使用它来访问库模块的内部API,甚至是JDK本身,但这样做的风险自负。如果内部API发生更改或被删除,则库或应用程序将失败。

参见JEP 261:模块系统。

--add-opens

一些工具和库使用反射API(setAccessible(true))来尝试访问java.*API的非公共字段和方法。在JDK17上,默认情况下这是不可能的,但您可以使用命令行上的--add-opens选项为特定的工具和库启用它。

--add opens的语法为:

复制

--add-opens <module>/<package>=<target-module>(,<target-module>)*

此选项允许<module>打开<package>到<target module>,而不考虑模块声明。

作为一种特殊情况,如果<目标模块>是ALL-UNNAMED,则源包将导出到所有未命名的模块,无论这些模块最初存在还是以后创建。例如:

复制

--add-opens java.management/sun.management=ALL-UNNAMED

此示例允许类路径上的所有代码访问java.management/sun.management包中公共类型的非公共成员。

注意:在Java Web Start的JNLP文件中,必须在--add open和它的值之间包含一个等号。

复制

<j2se version="10" java-vm-args="--add-opens=<module>/<package>=ALL-UNNAMED"  />

--add之间的等号打开,其值在命令行中是可选的。

新版本字符串方案

JDK10对JDK9中引入的版本字符串方案进行了一些小的更改,以更好地适应基于时间的发布模型。JDK11及更高版本保留了JDK10中引入的版本字符串格式。

如果您的代码依赖于版本字符串格式来区分主要、次要、安全和修补程序更新版本,那么您可能需要更新它。

新版本字符串的格式为:

$FEATURE.$INTERIM.$UPDATE.$PATCH

添加了一个简单的Java API来解析、验证和比较版本字符串。请参阅java.lang.Runtime.Version。

请参阅Java平台中的版本字符串格式,标准版安装指南。

有关JDK9中引入的版本字符串的更改,请参阅JEP223:NewVersionStringScheme。

有关JDK10中引入的版本字符串更改,请参阅JEP322:Time-Based Release Versioning。

对已安装JDK/JJRE映像的更改

JDK和JRE已进行了重大更改。

更改JDK和JRE布局

安装JDK后,如果查看文件系统,您会注意到目录布局与JDK9之前的版本不同。

JDK 11及更高版本

JDK 11及更高版本没有JRE映像。请参阅Java平台中JDK的已安装目录结构,标准版安装指南。

JDK 9和JDK 10

以前的版本有两种类型的运行时映像:JRE,它是Java SE平台的完整实现;JDK,它将整个JRE包含在JRE/目录中,再加上开发工具和库。

在JDK 9和JDK 10中,JDK和JRE是两种类型的模块化运行时映像,包含以下目录:

  • bin:包含二进制可执行文件。
  • conf:包含.properties、.policy和其他类型的文件,供开发人员、部署人员和最终用户编辑。这些文件以前是在lib目录或其子目录中找到的。
  • lib:包含动态链接的库和JDK的完整内部实现。

在JDK9和JDK10中,仍然有单独的JDK和JRE下载,但每个都有相同的目录结构。JDK映像包含JDK中历史上发现的额外工具和库。没有jdk/和jre/wrapper目录,二进制文件(如java命令)也不重复。

请参阅JEP 220:模块化运行时映像。

新的类加载器实现

JDK9和更高版本维护了自1.2版本以来存在的类加载器的层次结构。但是,为了实现模块系统,进行了以下更改:

应用程序类加载器不再是URLClassLoader的实例,而是内部类的实例。它是既不是JavaSE也不是JDK模块的模块中的类的默认加载程序。

扩展类加载程序已被重命名;它现在是平台类加载器。Java SE平台中的所有类都保证通过平台类加载器可见。

仅仅因为一个类通过平台类加载器可见,并不意味着该类实际上是由平台类加载器定义的。Java SE平台中的一些类由平台类加载器定义,而其他类则由引导类加载器定义。应用程序不应该依赖于哪个类加载器定义哪个平台类。

JDK9中实现的更改可能会影响创建以null(即引导类加载器)作为父类加载器的类加载器的代码,并假设所有平台类都对父类可见。这样的代码可能需要更改以使用平台类加载器作为父类(请参见ClassLoader.getPlatformClassLoader)。

平台类加载器不是URLClassLoader的实例,而是内部类的实例。

引导类加载器仍然内置于Java虚拟机中,并在ClassLoader API中用null表示。它定义了一些关键模块中的类,如java.base。因此,它定义的类比JDK8中定义的要少得多,因此使用-Xbootclasspath/a部署的应用程序或创建以null为父级的类加载器的应用程序可能需要如前所述进行更改。

删除了rt.jar和tools.jar

以前存储在lib/rt.jar、lib/tools.jar、lib/dt.jar和其他各种内部jar文件中的类和资源文件以更高效的格式存储在lib目录中的特定于实现的文件中。

删除rt.jar和类似文件会导致以下方面的问题:

从JDK9开始,ClassLoader.getSystemResource不会返回指向JAR文件的URL(因为没有JAR文件)。相反,它返回一个jrt URL,命名存储在运行时映像中的模块、类和资源,而不透露映像的内部结构或格式。

例如:


复制

ClassLoader.getSystemResource(“java/lang/Class.Class”);

当在JDK8上运行时,此方法返回以下形式的JAR URL:


复制

jar:文件:/usr/local/jdk8/jre/lib/rt.jar/java/lang/Class.Class

它嵌入一个文件URL来命名运行时映像中的实际JAR文件。

模块化映像不包含任何JAR文件,因此这种形式的URL毫无意义。在JDK9及更高版本上,此方法返回:

复制

jrt:/java.base/java/lang/Class.Class

java.security.CodeSource API和安全策略文件使用URL来命名要授予特定权限的代码库的位置。请参阅Java平台中的策略文件语法,标准版安全开发人员指南。运行时系统中需要特定权限的组件当前通过使用文件URL在conf/security/java.policy文件中进行标识。

旧版本的IDE和其他开发工具需要能够枚举存储在运行时映像中的类和资源文件,并通过打开和读取rt.jar和类似文件直接读取它们的内容。这在模块化图像中是不可能的。

删除了扩展机制

在JDK8及更早版本中,扩展机制使运行时环境可以查找和加载扩展类,而无需在类路径上专门命名它们。从JDK9开始,如果需要使用扩展类,请确保JAR文件位于类路径上。

在JDK9和JDK10中,如果设置了java.ext.dirs系统属性,或者存在lib/ext目录,则javac编译器和java启动器将退出。要额外检查特定于平台的系统范围目录,请指定-XX:+CheckEndorsedAndExtDirs命令行选项。如果目录存在且不为空,则会发生相同的退出行为。扩展类加载器保留在JDK 9(及更高版本)中,并被指定为平台类加载器(请参阅getPlatformClassLoader。)但是,在JDK 11中,此选项已过时,使用时会发出警告。

以下错误表示您的系统已配置为使用扩展机制:


复制

<JAVA_HOME>/lib/ext存在,不再支持扩展机制;请改用-classpath。

。错误:无法创建Java虚拟机。

错误:发生致命异常。程序将退出。

如果设置了java.ext.dirs系统属性,您将看到类似的错误。

要修复此错误,请删除ext/目录或java.ext.dirs系统属性。

请参阅JEP 220:模块化运行时映像。

删除了认可的标准覆盖机制

java.endorsed.dirs系统属性和lib/认可的目录已不存在。如果检测到任何一个,javac编译器和java启动器都将退出。

从JDK9开始,您可以使用可升级模块或将JAR文件放在类路径上。

该机制旨在让应用程序服务器覆盖JDK中使用的组件。要更新的包将被放入JAR文件中,系统属性java.endorsed.dirs将告诉java运行时环境在哪里可以找到它们。如果未指定此属性的值,则使用默认值$JAVA_HOME/lib/approved。

在JDK8中,您可以使用-XX:+CheckEndorsedAndExtDirs命令行参数来检查系统中任何位置的此类目录。

在JDK9及更高版本中,如果设置了java.endorsed.dirs系统属性,或者存在lib/认可的目录,则javac编译器和java启动器将退出。

以下错误表示您的系统配置为使用认可的标准覆盖机制:


复制

不支持<JAVA_HOME>/lib/approved。认可的标准和独立API

模块化形式将通过可升级模块的概念得到支持。

错误:无法创建Java虚拟机。

错误:发生致命异常。程序将退出。

如果设置了java.endorsed.dirs系统属性,您将看到类似的错误。

要修复此错误,请删除lib/认可的目录,或取消设置java.endorsed.dirs系统属性。

请参阅JEP 220:模块化运行时映像。

删除了macOS特定功能

本节包括从JDK9开始删除的macOS特定功能。

特定于平台的桌面功能

java.awt.Desktop类包含对Apple特定的com.Apple.eawt和com.Apple.eio包中API的替换。新的API取代了macOS API,并且是独立于平台的。

com.apple.eawt和com.apple.eio包中的API是封装的,因此您将无法在JDK9或更高版本中针对它们进行编译。但是,它们在运行时仍然可以访问,因此编译到旧版本的现有代码将继续运行。最终,使用apple和com.apple包及其子包中的内部类的库或应用程序将需要迁移到新的API。

com.apple.concurrent和apple.appescription包被删除,没有任何替换。

请参阅JEP 272:特定于平台的桌面功能。

已删除AppleScript引擎

AppleScript引擎,一个特定于平台的javax.script实现,已经被删除,JDK中没有任何替换。

AppleScript引擎在最近的版本中基本上不可用。该功能仅在JDK 7或JDK 8中有效,这些系统上已经有苹果版本的AppleScriptEngine.jar文件。

Windows注册表项更改

Java 11及更高版本的安装程序在安装JDK时会创建Windows注册表项。对于JDK 16,安装程序会创建以下Windows注册表项:

“HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK”

“HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK\16”

如果安装了JDK的两个版本,则会创建两个不同的Windows注册表项。例如,如果JDK 15.0.1与JDK 16一起安装,则安装程序会创建另一个Windows注册表项,如图所示:

“HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK”

“HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK\16”

“HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK\15.0.1”

部署

Java部署技术在JDK9中被弃用,在JDK11中被删除。

使用JDK9中引入的jlink工具来打包和部署专用的运行时,而不是依赖于预先安装的系统JRE。

删除了启动时JRE版本选择

从JDK9开始,请求不是在启动时启动的JRE版本的JRE的功能被删除。

现代应用程序通常使用Java Web Start(JNLP)、本机操作系统打包系统或活动安装程序进行部署。这些技术有自己的方法来管理所需的JRE,方法是根据需要查找或下载并更新所需的JRE。这使得启动器的启动时JRE版本选择过时。

在以前的版本中,您可以指定启动应用程序时要使用的JRE版本(或版本范围)。可以通过命令行选项和应用程序JAR文件中的清单条目进行版本选择。

从JDK 9开始,java启动器被修改如下:

如果在命令行中给定-version:选项,则发出错误消息并退出。

如果在JAR文件中找到JRE版本清单条目,则发出警告消息并继续。

请参阅JEP 231:删除启动时JRE版本选择。

删除了对序列化小程序的支持

从JDK9开始,不支持将小程序部署为序列化对象。使用现代压缩和JVM性能,以这种方式部署小程序没有任何好处。

启动小程序时,会忽略小程序标记的对象属性以及对象和java对象小程序参数标记。

使用标准部署策略,而不是序列化小程序。

JNLP规范更新

JNLP(Java网络启动协议)已经更新,以消除不一致,使代码维护更容易,并增强安全性。

在JDK9中,JNLP的更新如下:

  • &amp;而不是JNLP文件中的&。

JNLP文件语法符合XML规范,所有JNLP文件都应该能够由标准XML解析器解析。

JNLP文件允许您指定复杂的比较。以前,这是通过使用“与”符号(&)来完成的,但标准XML不支持这样做。如果您使用&来创建复杂的比较,请将其替换为&amp;在您的JNLP文件中&amp;与所有版本的JNLP兼容。

  • 将数字版本的元素类型与非数字版本元素类型进行比较。

以前,当一个int版本元素与另一个无法解析为int的版本元素进行比较时,版本元素会按照ASCII值进行字典比较。

如果可以解析为int的元素是比另一个元素更短的字符串,则在按ASCII值进行字典比较之前,它将填充前导零。这样可以确保不存在圆形。

在同时使用版本比较和JNLPservlet的情况下,应该只使用数值来表示版本。

  • 在java(或j2se)元素中具有嵌套资源的组件扩展。

这在规范中是允许的。它以前是受支持的,但这种支持没有反映在规范中。

  • FX XML扩展。

对JNLP规范进行了增强,为application-desc元素添加了一个type属性,并在application-desc中添加了子元素param(就像在applet-desc中一样)。

这不会对现有应用程序造成问题,因为仍然支持以前指定JavaFX应用程序的方式。

请参阅JSR-056中的JNLP规范更新。

垃圾收集的更改

本节介绍从JDK9开始对垃圾收集的更改。

将G1设为默认垃圾回收器

Garbage-FirstGarbageCollector(G1GC)是JDK9及更高版本中的默认垃圾收集器。

对于大多数用户来说,像G1GC这样的低暂停收集器应该比像ParallelGC这样的面向吞吐量的收集器(JDK8默认值)提供更好的整体体验。

有关调整G1 GC的更多信息,请参阅Java平台中G1 GC的人机工程学默认值和可调整默认值,标准版热点虚拟机垃圾收集调整指南。

删除了GC选项

以下GC组合将导致您的应用程序无法在JDK 9及更高版本中启动:

  • DefNew+CMS
  • ParNew+SerialOld
  • 增量CMS

CMS的前台模式也已被删除。已删除的命令行标志为-Xincgc、-XX:+CMSIncrementalMode、-XX:+UseCMSCompactAtFullCollection、-XX:+CMSFullGCsBeforeCompaction和-XX:+UseCMSCollectionPassing。

命令行标志-XX:+UseParNewGC不再有效。ParNew标志只能与CMS一起使用,CMS需要ParNew。因此,-XX:+UseParNewGC标志已被弃用,可以在将来的版本中删除。

请参阅JEP 214:删除JDK 8中不推荐的GC组合。

注意:CMS垃圾收集器已被删除。请参阅JEP 363:删除并发标记扫描(CMS)垃圾收集器。

删除永久代(Permanent Generation)

JDK8中删除了永久代,相关的VM选项导致打印警告。您应该从脚本中删除以下选项:

-XX: MaxPermSize=大小

-XX: PermSize=大小

在JDK9及更高版本中,JVM显示如下警告:

复制

Java HotSpot(TM)64位服务器VM警告:忽略选项MaxPermSize;8.0中删除了支持

了解永久生成的工具可能需要更新。

请参阅JEP 122:删除永久生成和JDK 9发行说明-删除的API、功能和选项。

GC日志输出的更改

垃圾回收(GC)日志使用JVM统一的日志框架,新日志和旧日志之间存在一些差异。您正在使用的任何GC日志解析器都可能需要更改。

您可能还需要更新JVM日志记录选项。所有与GC相关的日志记录都应该使用GC标记(例如,--Xlog:GC),通常与其他标记结合使用。-XX:+PrintGCDetails和-XX:+PrintGC选项已被弃用。

请参阅Java开发工具包工具规范中的“使用JVM统一日志记录框架启用日志记录”和JEP 271:统一GC日志记录。

运行Java小程序

如果您仍然依赖小程序,则可以在Internet Explorer模式下使用JRE 8和Microsoft Edge在Windows系统上启动它们。请参阅Microsoft Edge+Internet Explorer模式:入门指南。

截至2021年9月,启动Applets所需的Java插件仍在Java 8的Windows上更新,但可能在未来的更新版本中随时删除。

Oracle客户可以在My.Oracle.Support Note 251148.1-Java SE 8 Java插件结束支持(需要登录)上找到更多信息。

正则表达式匹配中的行为变化

java.util.regex.Pattern类在带有方括号的正则表达式中定义字符类。例如,[abc]匹配a、b或c。带负号的字符类是用紧跟在左大括号后面的插入符号定义的。例如,[^abc]匹配除a、b或c之外的任何字符。

在JDK8及更早版本中,否定的字符类不会否定嵌套的字符类。例如,[^a-b[c-d]e-f]匹配c,但不匹配a或e,因为它们不在嵌套类中。运算符被一个接一个地应用。在本例中,在嵌套之前应用否定运算符^。在JDK8及更早版本中,运算符^仅应用于字符类中最外层的字符,而不应用于嵌套的字符类。这种行为令人困惑,难以理解。

然而,在JDK9及更高版本中,否定运算符被应用于所有嵌套的字符类。例如,[^a-b[c-d]e-f]与c不匹配。

为了进一步解释,请考虑以下正则表达式:

复制

[^a-d&&c-f]

在JDK8中,^运算符首先应用,因此此示例被解释为[^a-d]与[c-f]相交。这匹配e和f,但不匹配a、b、c或d。

在JDK9及更高版本中,&&运算符首先应用,因此此示例被解释为[a-d]&&[c-f]的补码。这匹配a、b、e和f,但不匹配c或d。

作为最佳实践,请查找使用具有否定类、交集类和嵌套类组合的字符类的正则表达式。这些正则表达式可能需要进行调整,以考虑到更改后的行为。

安全管理器已弃用并删除

在JDK17中,安全管理器和与其相关的API已被弃用,并将在未来的版本中删除。安全管理器无法替代。讨论和备选方案见JEP 411。

 
 

标签