多读书多实践,勤思考善领悟

Oracle JDK迁移指南,JDK11变化详解,JDK8升级JDK11详细指南

本文于1657天之前发表,文中内容可能已经过时。

官方英文原版: https://docs.oracle.com/en/java/javase/11/migrate/index.html#JSMIG-GUID-C25E2B1D-6C24-4403-8540-CFEA875B994A

Oracle JDK迁移指南

第11版

E94894-03

2019年7月

入门

本指南的目的是帮助您识别潜在问题,并在将现有Java应用程序迁移到最新JDK版本时为您提供有关如何继续的建议。该指南还强调了对最新版本所做的重大更改和增强。

本指南包含以下部分:

JDK 11发布的重大变化

在将应用程序迁移到JDK 11之前,您应该了解它与JDK 10版本之间的更新和更改。如果要从JDK 8迁移,则还应熟悉从JDK 8迁移到以后的JDK版本中描述的JDK 8和更高版本之间的差异。

以下是JDK 11中的一些重要更改:

此外,还需要了解与安全相关的更新以及很少删除的工具和组件。看到:

删除部署堆栈

Java部署技术在JDK 9中已弃用,在JDK 11中已删除。

Java applet和Web Start功能,包括Java插件,Java Applet Viewer,Java控制面板和Java Web Start,以及javaws工具,已在JDK 11中删除。

请参阅 删除Java部署技术

删除Java EE和CORBA模块

在JDK 11中,删除了Java EE和CORBA模块。不推荐在JDK 9中删除这些模块。

删除的模块是:

  • java.xml.ws:用于XML Web服务的Java API(JAX-WS),用于Java平台的Web服务元数据以及用于Java的附件的SOAP(SAAJ)
  • java.xml.bind:用于XML绑定的Java体系结构(JAXB)
  • java.xml.ws.annotation:Java SE定义的JSR-250 Common Annotations的子集,用于支持Web服务
  • java.corba:CORBA
  • java.transaction:Java SE定义的Java Transaction API的子集,用于支持CORBA对象事务服务
  • java.activation:JavaBeans Activation Framework
  • java.se.ee:上面六个模块的聚合器模块
  • jdk.xml.ws:JAX-WS的工具
  • jdk.xml.bind:JAXB的工具

如果不更改构建,则不会编译引用这些API中的类的现有代码。同样,在这些API类的引用的类路径上的代码将失败,NoDefClassFoundError或者ClassNotFoundException,除非改变了应用程序的部署制成。

请参阅JEP 320:删除Java EE和CORBA模块以获取有关模块可能替换的更多信息。

注意:

您可以从Maven下载JAXB和JAX-WS。

安全更新

JDK 11发行版中的安全更新

JDK 11版本包括传输层安全性(TLS)1.3规范(RFC 8446)的实现。

TLS 1.3是传输层安全性(TLS)协议的最新版本(2018年8月),默认情况下在JDK 11中启用。该版本不仅关注速度改进,还通过强调现代加密技术来更新协议的整体安全性。实践,并禁止过时或弱的加密算法。(例如,不再允许RSA密钥交换和普通DSA签名。)

TLS 1.3协议中添加了一些功能以提高向后兼容性,但有几个问题需要注意。有关详细信息,请参阅JEP 332

删除安全证书

已从JDK 11中的密钥库中删除以下根证书:

已从JDK 11中的信任库中删除以下根证书:

使用已删除的证书的产品可能不再有效。如果需要这些证书,则必须使用缺少的证书配置和填充cacerts。为了证书添加到信任,看到密钥工具在Java平台,标准版工具参考指南。

删除了API,工具和组件

本节提供有关在JDK 11中删除的API,工具和组件的详细信息。

在JDK 11中删除了API

JDK 11中删除了以下API。许多这些API在以前的版本中已弃用,并且已被更新的API替换。有关可能的替代方案的信息,请参阅JDK 11 API规范

1
2
3
4
5
6
7
8
9
javax.security.auth.Policy 
java.lang.Runtime.runFinalizersOnExit(boolean)
java.lang.SecurityManager.checkAwtEventQueueAccess()
java.lang.SecurityManager.checkMemberAccess(java.lang.Class,int)
java.lang.SecurityManager.checkSystemClipboardAccess()
java.lang.SecurityManager.checkTopLevelWindow(java.lang.Object)
java.lang.System.runFinalizersOnExit(boolean)
java.lang.Thread.destroy()
java.lang.Thread.stop(java.lang.Throwable)

JDK 11未附带的工具和组件

以下是JDK 11未附带的工具和组件列表。

主要工具

  • appletviewer

请参阅JDK-8200146:删除appletviewer启动器

CORBA工具

  • idlj
  • orbd
  • servertool
  • tnamesrv

此外,rmic(RMI编译器)将不再支持-idl-iiop选项。请参阅 JDK 11发行说明

Java Web服务工具

  • schemagen
  • wsgen
  • wsimport
  • xjc

请参阅JEP 320:删除Java EE和CORBA模块

Java部署工具

  • javapackager
  • javaws

注意:

pack 200并且unpack200已被弃用,可能会在将来的JDK版本中删除。

请参阅从JDKJEP中删除JavaFX 336:弃用Pack200工具和API

监控工具

  • jmc:在JDK 11中,JMC作为独立程序包提供,而不是捆绑在JDK中。

请参阅从JDKJava Mission Control中删除JMC

JVM管理-MIB.mib中

JVM-MANAGEMENT-MIB.mib已删除通过SNMP进行JVM监视和管理的规范。请参阅删除JVM-MANAGEMENT-MIB.mib

SNMP代理

jdk.snmp模块已被删除。请参阅删除SNMP代理

Oracle桌面特定删除

  • Oracle JDK T2K字体光栅器已被删除。
  • Lucida字体:Oracle JDK不再提供任何字体,完全依赖于操作系统上安装的字体。请参阅从Oracle JDK中删除Lucida字体

准备迁移

以下部分将帮助您成功迁移您的应用程序:

下载最新的JDK

下载并安装最新的JDK版本

在重新编译之前运行程序

尝试在最新的JDK版本(JDK 11)上运行您的应用程序。大多数代码和库应该在JDK 11上运行而不做任何更改,但可能有一些库需要升级。

注意:

迁移是一个迭代过程。你可能会发现最好先尝试运行你的程序(这个任务),然后或多或少并行地完成这三个任务:

运行应用程序时,请从JVM中查找有关过时VM选项的警告。如果VM无法启动,请查找已删除的GC选项

如果您的应用程序成功启动,请仔细查看您的测试并确保其行为与您使用的JDK版本相同。例如,一些早期采用者注意到他们的日期和货币格式不同。请参阅默认使用CLDR区域设置数据

要使代码适用于最新的JDK版本,请了解每个JDK版本中的新功能和更改。

即使您的程序似乎成功运行,您也应该完成本指南中的其余步骤并查看问题列表。

更新第三方库

对于您使用的每个工具和第三方库,您可能需要具有支持最新JDK版本的更新版本。

检查第三方库和工具供应商的网站,以获取适用于最新JDK的每个库或工具的版本。如果存在,则下载并安装新版本。

如果使用Maven或Gradle构建应用程序,请确保升级到支持最新JDK版本的更新版本。

如果使用IDE开发应用程序,则可能有助于迁移现有代码。NetBeans,Eclipse和IntelliJ IDE都有可用的版本,包括对最新JDK的支持。

您可以在OpenJDK wiki的Quality Outreach上看到OpenJDK 构建的许多免费开源软件(FOSS)项目的测试状态。

如果需要,编译您的应用程序

使用最新的JDK编译器编译代码将简化向未来版本的迁移,因为代码可能依赖于已被确定为有问题的API和功能。但是,并非绝对必要。

如果需要使用JDK 11编译器编译代码,请注意以下事项:

  • 如果在源代码中使用下划线字符(“_”)作为单字符标识符,则代码将无法在JDK 11中编译。它在JDK 8中生成警告,并从JDK 9开始生成错误。

    举个例子:

    1
    static Object _ = new Object();

    此代码从编译器生成以下错误消息:

    1
    MyClass.java:2: error: as of release 9, '_' is a keyword, and may not be used as a legal identifier.
  • 如果使用-source-target选项javac,则检查您使用的值。

    支持的-source/-target值为11(默认值),10,9,8,7和6(不推荐使用6,并且在使用此值时会显示警告)。

    在JDK 8,-source-target1.5 / 5的值和更早被弃用,并引起了警告。在JDK 9及更高版本中,这些值会导致错误。

    1
    2
    3
    4
    >javac -source 5 -target 5 Sample.java 
    warning: [options] bootstrap class path not set in conjunction with -source 5
    error: Source option 5 is no longer supported. Use 6 or later.
    error: Target option 1.5 is no longer supported. Use 1.6 or later.

    如果可能,请使用新--release标志而不是 -source-target选项。见javac的在Java平台,标准版工具参考。

    --release标志的有效参数遵循与之相同的策略,-source并且-target一加三后退。

    javac可以识别和处理所有以前的JDK的类文件,一直回到JDK 1.0.2类文件。

    请参阅JEP 182:退休javac -source和-target选项的政策

  • 在JDK 11中仍然可以访问关键的内部JDK API,例如sun.misc.Unsafe,但是在编译时无法访问大多数JDK的内部API。您可能会收到编译错误,指出您的应用程序或其库依赖于内部API。

    要标识依赖项,请运行Java依赖关系分析工具。请参阅在您的代码上运行jdeps。如果可能,请更新代码以使用支持的替换API。

    您可以使用该--add-exports选项作为临时解决方法来编译源代码,并引用JDK内部类。

  • 您可能会看到比以前更多的弃用警告。

在您的代码上运行jdeps

jdeps在应用程序上运行该工具,以查看应用程序和库所依赖的包和类。如果您使用内部API,则jdeps可以建议替换以帮助您更新代码。

要查找内部JDK API的依赖项,请jdeps使用该-jdkinternals选项运行。例如,如果您jdeps在调用的类上运行sun.misc.BASE64Encoder,您将看到:

1
2
3
4
5
6
7
8
9
10
11
12
13
>jdeps -jdkinternals Sample.class
Sample.class -> JDK removed internal API
Sample -> sun.misc.BASE64Encoder JDK internal API (JDK removed internal API)

Warning: JDK internal APIs are unsupported and private to JDK implementation that are
subject to be removed or changed incompatibly and could break your application.
Please modify your code to eliminate dependency on any JDK internal APIs.
For the most recent update on JDK internal API replacements, please check:
https://wiki.openjdk.java.net/display/JDK8/Java+Dependency+Analysis+Tool

JDK Internal API Suggested Replacement
---------------- ---------------------
sun.misc.BASE64Encoder Use java.util.Base64 @since 1.8

如果您使用Maven,则可以使用jdeps 插件。

有关jdeps语法,请参阅Java平台标准版工具参考中的jdeps

请记住,这jdeps是一个静态分析工具,代码的静态分析可能无法提供完整的依赖项列表。如果代码使用反射来调用内部API,则jdeps不会发出警告。

从JDK 8迁移到以后的JDK版本

JDK 8和后来的JDK版本之间发生了重大变化。

Every new Java SE release introduces some binary, source, and behavioral incompatibilities with previous releases. The modularization of the Java SE Platform that happened in JDK 9 brought many benefits, but also many changes. Code that uses only official Java SE Platform APIs and supported JDK-specific APIs should continue to work without change. Code that uses JDK-internal APIs should continue to run but should be migrated to use the supported APIs.

The following sections describe the changes in the JDK package and APIs that you should be aware of when migrating your JDK 8 applications to later JDK releases.

Look at the list of changes that you may encounter as you run your application.

When your application is running successfully on the latest version of JDK, review Next Steps, which will help you avoid problems with future releases.

Understanding Runtime Access Warnings

Some tools and libraries use reflection to access parts of the JDK that are meant for internal use only. This illegal reflective access will be disabled in a future release of the JDK. Currently, it is permitted by default and a warning is issued.

For example, here is the warning issued when starting Jython:

1
2
3
4
5
6
7
>java -jar jython-standalone-2.7.0.jar
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by jnr.posix.JavaLibCHelper (file:/C:/Jython/jython2.7.0/jython-standalone-2.7.0.jar) to method sun.nio.ch.SelChImpl.getFD()
WARNING: Please consider reporting this to the maintainers of jnr.posix.JavaLibCHelper
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
Jython 2.7.0 (default:9987c746f838, Apr 29 2015, 02:25:11)

如果您看到这样的警告,请联系工具或库的维护人员。警告的第二行命名精确的JAR文件,其代码使用反射来访问JDK的内部部分。

默认情况下,在java启动程序启动的进程的生命周期中,最多会发出一条有关反射访问的警告。警告的确切时间取决于执行反射访问操作的工具和库的行为。警告可能会在过程的生命周期的早期出现,也可能在启动后很长时间出现。

您可以使用--add-opens命令行标志在逐个库的基础上禁用警告消息。例如,您可以通过以下方式启动Jython:

1
2
>java --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED -jar jython-standalone-2.7.0.jar
Jython 2.7.0 (default:9987c746f838, Apr 29 2015, 02:25:11)

这次,不发出警告,因为java调用明确地确认了反射访问。如您所见,您可能需要指定多个--add-opens标志来涵盖类路径上的库尝试的所有反射访问操作。

为了更好地理解工具和库的行为,可以使用命令行标志。该标志导致为每个非法反射访问操作发出警告消息。此外,您还可以通过设置获取有关非法反射访问操作(包括堆栈跟踪)的详细信息。 --illegal-access=warn`–illegal-access=debug`

如果您更新了库,或者获得了库,那么您可以尝试使用命令行标志。除了由其他命令行选项启用的操作外,它禁用所有反射访问操作,例如。这将是未来版本中的默认模式。 --illegal-access=deny`–add-opens`

有两个选项可以让您以特定方式打破封装。您可以结合使用它们,或者如前所述,来抑制警告。 --illegal-access=deny

  • 如果需要使用已无法访问的内部API,请使用--add-exports运行时选项。您还可以--add-exports在编译时使用来访问内部API。
  • 如果必须允许类路径上的代码进行深入反射以访问非公共成员,请使用该--add-opens选项。

如果要禁止所有反射访问警告,请在需要时使用--add-exports--add-opens选项。

–add-exports

如果必须使用默认情况下无法访问的内部API,则可以使用--add-exports命令行选项中断封装。

--add-exports

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

其中<source-module>``

The --add-exports option allows code in the target module to access types in the named package of the source module if the target module reads the source module.

As a special case, if the , then the source package is exported to all unnamed modules, whether they exist initially or are created later on. For example:This example allows code in all unnamed modules (code on the class path) to access the public members of public types injava.management/sun.management

If an application package of thejava.managementmodule, then the access that it requires can be granted in this way:

You can also break encapsulation with the JAR file manifest:

1
Add-Exports:java.management/sun.management

Use the --add-exports option carefully. You can use it to gain access to an internal API of a library module, or even of the JDK itself, but you do so at your own risk. If that internal API changes or is removed, then your library or application fails.

See also JEP 261.

–add-opens

If you have to allow code on the class path to do deep reflection to access nonpublic members, then use the --add-opensruntime option.

Some libraries do deep reflection, meaning setAccessible(true), so they can access all members, including private ones. You can grant this access using the --add-opens option on the java command line. No warning messages are generated as a result of using this option.

If --illegal-access=deny, and you see IllegalAccessException or InaccessibleObjectExceptionmessages at runtime, you could use the --add-opens runtime option, basing the arguments upon the information shown in the exception message.

The syntax for

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

This option allows , regardless of the module declaration.

As a special case, if the , then the source package is exported to all unnamed modules, whether they exist initially or are created later on. For example:This example allows all of the code on the class path to access nonpublic members of public types in thejava.management/sun.managementpackage.

Note:

If you are using the JNI Invocation API, including, for example, a Java Web Start JNLP file, you must include an equals sign between

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

The equals sign between --add-opens and its value is optional on the command line.

New Version-String Scheme

JDK 10 introduced some minor changes, to better accommodate the time-based release model, to the version-string scheme introduced in JDK 9. JDK 11 retains the version string format that was introduced in JDK 10.

If your code relies on the version-string format to distinguish major, minor, security, and patch update releases, then you may need to update it.

The format of the new version-string is:

1
$FEATURE.$INTERIM.$UPDATE.$PATCH

A simple Java API to parse, validate, and compare version strings has been added. See java.lang.Runtime.Version.

See Version String Format in Java Platform, Standard Edition Installation Guide .

For the changes to the version string introduced in JDK 9, see JEP 223: New Version-String Scheme .

For the version string changes introduced in JDK 10, see JEP 322: Time-Based Release Versioning.

Changes to the Installed JDK/JRE Image

Significant changes have been made to the JDK and JRE.

Changed JDK and JRE Layout

After you install the JDK, if you look at the file system, you’ll notice that the directory layout is different from that of releases before JDK 9.

JDK 11

JDK 11 does not have the JRE image. See Installed Directory Structure of JDK in Java Platform, Standard Edition Installation Guide.

JDK 9 and JDK 10

Prior releases produced two types of runtime images: the JRE, which was a complete implementation of the Java SE Platform, and the JDK, which included the entire JRE in a jre/ directory, plus development tools and libraries.

In JDK 9 and and JDK 10, the JDK and JRE are two types of modular runtime images, where each contains the following directories:

  • bin: contains binary executables.
  • conf: contains .properties, .policy, and other kinds of files intended to be edited by developers, deployers, and end users. These files were formerly found in the lib directory or its subdirectories.
  • lib: contains dynamically linked libraries and the complete internal implementation of the JDK.

在JDK 9和JDK 10中,仍然有单独的JDK和JRE下载,但每个都具有相同的目录结构。JDK映像包含历史上在JDK中找到的额外工具和库。没有jdk/jre/包装目录相对应,并且二进制文件(例如java命令)不会重复。

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

新的类加载器实现

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

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

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

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

    在JDK 9中实现的更改可能会影响使用null(即引导类加载器)创建类加载器的代码作为父类加载器,并假定所有平台类对父级是可见的。可能需要更改此类代码以使用平台类加载器作为父代(请参阅ClassLoader.getPlatformClassLoader))。

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

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

删除了JDK 9中的rt.jar和tools.jar

类和资源文件之前存储在lib/rt.jarlib/tools.jarlib/dt.jar和其他各种内部JAR文件都存储在一个更有效的格式在实现特定的文件lib目录。

删除rt.jar和类似文件会导致这些方面出现问题:

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

    例如:

    1
    ClassLoader.getSystemResource("java/lang/Class.class");

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

    1
    jar:file:/usr/local/jdk8/jre/lib/rt.jar!/java/lang/Class.class

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

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

    1
    jrt:/java.base/java/lang/Class.class
  • The java.security.CodeSource API and security policy files use URLs to name the locations of code bases that are to be granted specific permissions. See Policy File Syntax in Java Platform, Standard Edition Security Developer’s Guide. Components of the runtime system that require specific permissions are currently identified in the conf/security/java.policy file by using file URLs.

  • Older versions of IDEs and other development tools require the ability to enumerate the class and resource files stored in a runtime image, and to read their contents directly by opening and reading rt.jar and similar files. This isn’t possible with a modular image.

Removed Extension Mechanism in JDK 9

In JDK 8 and earlier, the extension mechanism made it possible for the runtime environment to find and load extension classes without specifically naming them on the class path. Starting from JDK 9, if you need to use the extension classes, ensure that the JAR files are on the class path.

In JDK 9 and JDK 10, the javac compiler and java launcher will exit if the java.ext.dirs system property is set, or if the lib/ext directory exists. To additionally check the platform-specific systemwide directory, specify the -XX:+CheckEndorsedAndExtDirs command-line option. This causes the same exit behavior to occur if the directory exists and isn’t empty. The extension class loader is retained in JDK 9 (and later releases) and is specified as the platform class loader (see getPlatformClassLoader).) However, in JDK 11, this option is obsolete and a warning is issued when it is used.

The following error means that your system is configured to use the extension mechanism:

1
2
3
<JAVA_HOME>/lib/ext exists, extensions mechanism no longer supported; Use -classpath instead.
.Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

You’ll see a similar error if the java.ext.dirs system property is set.

To fix this error, remove the ext/ directory or the java.ext.dirs system property.

See JEP 220: Modular Run-Time Images.

Removed Endorsed Standards Override Mechanism

The java.endorsed.dirs system property and the lib/endorsed directory are no longer present. The javaccompiler and java launcher will exit if either one is detected.

Starting from JDK 9, you can use upgradeable modules or put the JAR files on the class path.

This mechanism was intended for application servers to override components used in the JDK. Packages to be updated would be placed into JAR files, and the system property java.endorsed.dirs would tell the Java runtime environment where to find them. If a value for this property wasn’t specified, then the default of $JAVA_HOME/lib/endorsed was used.

In JDK 8, you can use the -XX:+CheckEndorsedAndExtDirs command-line argument to check for such directories anywhere on the system.

In JDK 9 and later releases, the javac compiler and java launcher will exit if the java.endorsed.dirs system property is set, or if the lib/endorsed directory exists.

The following error means that your system is configured to use the endorsed standards override mechanism:

1
2
3
4
<JAVA_HOME>/lib/endorsed is not supported. Endorsed standards and standalone APIs
in modular form will be supported via the concept of upgradeable modules.
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

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

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

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

Windows注册表项更改

安装JDK时,Java 11安装程序会创建这些Windows注册表项:

  • “HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK”
  • “HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK\11”

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

  • “HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK”
  • “HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK\11.0.1”

删除或更改的API

本节重点介绍在默认行为中无法访问,删除或更改的API。编译或运行应用程序时,您可能会遇到本节中描述的问题。

请参阅JDK 11中的已删除API

删除了JDK 9和JDK 10中的API

以下是从JDK 9和JDK 10发行版中删除的一些重要API。

删除了java。* API

Java团队致力于向后兼容。如果应用程序在JDK 8中运行,那么它将在JDK 9及更高版本上运行,只要它使用支持并供外部使用的API即可。

这些包括:

  • JCP标准,java。,javax。
  • JDK特定的API,一些com.sun。,一些jdk。

可以从JDK中删除支持的API,但只能通知。通过运行静态分析工具jdeprscan,了解您的代码是否使用了弃用的API 。

java。*在JDK 9中删除的API包括java.util.logging.LogManager和java.util.jar.Pack200包中以前弃用的方法:

1
2
3
4
5
6
java.util.logging.LogManager.addPropertyChangeListener
java.util.logging.LogManager.removePropertyChangeListener
java.util.jar.Pack200.Packer.addPropertyChangeListener
java.util.jar.Pack200.Packer.removePropertyChangeListener
java.util.jar.Pack200.Unpacker.addPropertyChangeListener
java.util.jar.Pack200.Unpacker.removePropertyChangeListener

删除和将来删除sun.misc和sun.reflect API

与java。 API不同,几乎所有sun。 API都不受支持,JDK内部API,并且可能随时消失。

在JDK 9中删除了一些sun。* API。值得注意的是,sun.misc.BASE64Encoder和sun.misc.BASE64Decoder被删除了。而是使用受支持的java.util.Base64类,该类在JDK 8中添加。

如果您使用这些API,则可能希望迁移到其支持的替换项:

  • sun.misc.Unsafe

    通过使用变量句柄可以使用此类中的许多方法的功能,请参阅JEP 193:可变句柄

  • sun.reflect.Reflection :: getCallerClass(INT)

    相反,使用stack-walking API,请参阅JEP 259:Stack-Walking API

请参阅JEP 260:封装大多数内部API

java.awt.peer不可访问

该java.awt.peer中和java.awt.dnd.peer包无法访问,在JDK 9开始的包从来没有在Java SE API的一部分,尽管是java中。*命名空间。

引用这些包中定义的类型的Java SE API中的所有方法都从JDK 9中删除。调用先前接受或返回在这些包中定义的类型的方法的代码不再编译或运行。

java.awt.peer

  • 要查看是否已设置对等方:

    1
    if (component.getPeer() != null) { .. }

    将其替换为JDK 1.1 API中的

    Component.isDisplayable()

    1
    2
    public boolean isDisplayable() {
    return getPeer() != null;
  • 要测试组件是否轻量级:

    1
    if (component.getPeer() instanceof LightweightPeer) ..

    将其替换为JDK 1.2 API中的

    Component.isLightweight()

    1
    2
    public boolean isLightweight() {
    return getPeer() instanceof LightweightPeer;

删除了com.sun.image.codec.jpeg包

非标准包com.sun.image.codec.jpeg已被删除。请改用Java Image I / O API。

该的com.sun.image.codec.jpeg包JDK 1.2中加入作为控制装载和JPEG格式的图像文件的保存的一个非标准的方式。它从未成为平台规范的一部分。

在JDK 1.4中,Java Image I / O API作为标准API添加,位于javax.imageio包中。它提供了一种标准机制,用于控制采样图像格式的加载和保存,并要求所有兼容的Java SE实现都支持基于Java Image I / O规范的JPEG。

删除了压缩配置文件的工具支持

从JDK 9开始,您可以选择针对Java运行时映像中的任何模块子集构建和运行应用程序,而无需依赖预定义的配置文件。

Java SE 8中引入的配置文件定义了Java SE Platform API的子集,这些子集可以减少存储容量有限的设备上Java运行时的静态大小。在JDK 8支持工具三个配置文件,compact1compact2,和compact3。有关每个配置文件的API组合,请参阅JDK 8文档中的详细配置文件组合API参考

在JDK 8中,您可以使用该-profile选项在运行javacjava命令时指定配置文件。从JDK 9开始,该-profile选项javac仅与该--release 8选项一起支持,并且不受支持java

JDK 9及更高版本允许您选择在编译和运行时使用的模块。通过使用新--limit-modules选项指定模块,您可以获得紧凑配置文件中的相同API。该选项是由两个支持javacjava命令,如在以下实施例:

1
2
javac --limit-modules java.base,java.logging MyApp.java
java --limit-modules java.base,java.logging MyApp

为Java SE 8中的每个配置文件指定的包将由以下几组模块共同导出:

  • 对于compact1配置文件:java.base,java.logging,java.scripting
  • 对于compact2配置文件:java.base,java.logging,java.scripting,java.rmi,java.sql,java.xml
  • 对于compact3配置文件:java.base,java.logging,java.scripting,java.rmi,java.sql,java.xml,java.compiler,java.instrument,java.management,java.naming,java.prefs,java。 security.jgss,java.security.sasl,java.sql.rowset,java.xml.crypto

您可以使用该jdeps工具对源代码中使用的Java包进行静态分析。这为您提供了执行应用程序所需的一组模块。compact3例如,如果您一直在使用该 配置文件,那么您可能会发现在构建应用程序时不需要包含整套模块。见jdeps在Java平台,标准版工具参考。

请参阅JEP 200:模块化JDK

默认情况下使用CLDR区域设置数据

从JDK 9开始,Unicode Consortium的公共区域设置数据存储库(CLDR)数据作为默认区域设置数据启用,因此您可以使用标准区域设置数据而无需任何进一步操作。

在JDK 8中,虽然CLDR区域设置数据与JRE捆绑在一起,但默认情况下不启用它。

使用区域设置敏感服务(如日期,时间和数字格式)的代码可能会使用CLDR区域设置数据生成不同的结果。请记住,即使System.out.printf()也可以识别区域设置。

要启用与JDK 8兼容的行为,请将系统属性设置为例如前面的java.locale.providers值。COMPAT`CLDRjava.locale.providers=COMPAT,CLDR`

CLDR语言环境数据通过默认启用的Java平台,标准版国际指南和JEP 252:使用CLDR语言环境数据的默认

部署

Java部署技术在JDK 9中已弃用,在JDK 11中已删除。

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

删除了启动时JRE版本选择

从JDK 9开始,删除了请求从发布时启动的JRE版本的JRE版本的能力。

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

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

从JDK 9开始,java

  • 如果-version:在命令行上给出了选项,则发出错误消息并退出。
  • 如果JRE-Version在JAR文件中找到清单条目,则发出警告消息并继续。

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

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

从JDK 9开始,不支持将applet部署为序列化对象的能力。借助现代压缩和JVM性能,以这种方式部署applet没有任何好处。

object该属性applet标签和objectjava objectapplet的参数标签启动小程序时被忽略。

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

JNLP规范更新

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

JNLP已更新如下:

  1. 1
    &amp;

    而不是

    1
    &

    在JNLP文件中。

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

    JNLP文件允许您指定复杂的比较。以前,这是通过使用ampersand(&)完成的,但标准XML不支持此功能。如果您正在使用&创建复杂的比较,请&amp;在JNLP文件中替换它。&amp;与所有版本的JNLP兼容。

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

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

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

    在使用版本比较和JNLP servlet的情况下,您应该仅使用数值来表示版本。

  3. 具有

    1
    java

    (或

    1
    j2se

    )元素中嵌套资源的组件扩展。

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

  4. FX XML扩展。

    该JNLP规范已经增强,一个添加type属性application-desc元素,并添加子元素paramapplication-desc(因为它已经是applet-desc)。

    这不会导致现有应用程序出现问题,因为仍然支持以前指定JavaFX应用程序的方法。

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

JDK 9中的安全更新

从JDK 9开始,一些与安全相关的默认值已更改。

JCE管辖权政策文件默认为无限制

如果您的应用程序以前需要Java Cryptography Extension(JCE)Unlimited Strength Jurisdiction Policy Files,那么您不再需要下载或安装它们。它们包含在JDK中,默认情况下处于激活状态。

如果您的国家/地区或用途需要更严格的策略,则仍然可以使用有限的Java加密策略文件。

如果默认情况下提供的任一策略文件都不满足要求,则可以自定义这些策略文件以满足您的需要。

请参阅文件中的crypto.policySecurity属性<java-home>/conf/security/java.security,或Java平台标准版安全开发人员指南中的加密强度配置

建议您咨询您的出口/进口控制律师或律师,以确定具体要求。

创建PKCS12密钥库

我们建议您为密钥库使用PKCS12格式。此格式是默认密钥库类型,基于RSA PKCS12个人信息交换语法标准。

请参阅创建密钥库与JSSE使用的Java平台,标准版安全开发人员指南和密钥工具在Java平台,标准版工具参考。

垃圾收集的变化

本节介绍从JDK 9开始的垃圾回收更改。

使G1成为默认垃圾收集器

Garbage-First垃圾收集器(G1 GC)是JDK 9及更高版本中的默认垃圾收集器。

对于大多数用户而言,低暂停收集器(例如G1 GC)应该提供比面向吞吐量的收集器更好的整体体验,例如Parallel GC,它是JDK 8的默认值。

为G1 GC人体工学默认值可调默认的Java平台,标准版Java虚拟机指南有关调整G1 GC的更多信息。

删除了GC选项

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

  • DefNew + CMS
  • ParNew + SerialOld
  • Incremental CMS

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

命令行标志-XX:+UseParNewGC不再有效。该ParNew标志只能用于CMS和CMS要求ParNew。因此,该-XX:+UseParNewGC标志已被弃用,并且有资格在将来的版本中删除。

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

删除了永久世代

在JDK 8中删除了永久代,并且相关的VM选项会导致打印警告。您应该从脚本中删除这些选项:

  • -XX:MaxPermSize=size
  • -XX:PermSize=size

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

1
Java HotSpot(TM) 64-Bit Server VM warning: Ignoring option MaxPermSize; support was removed in 8.0

知道永久代的工具可能需要更新。

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

GC日志输出的更改

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

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

请参阅启用与JVM统一日志框架记录在Java平台,标准版工具参考和JEP 271:统一GC日志记录

删除了工具和组件

此列表包括不再与JDK捆绑在一起的工具和组件。

要了解有关JDK 11中删除的工具和组件的更多信息,请参阅JDK 11中的已删除API

删除了Native-Header生成工具(javah)

javah工具已被优越的功能所取代javac。它已在JDK 10中删除。

从JDK 8开始,javac提供了在编译Java源代码时编写本机头文件的功能,从而无需单独的工具。

而不是javah

1
javac -h

删除了JavaDB

JavaDB是Apache Derby的品牌重塑,不再包含在JDK中。

JavaDB与JDK 7和JDK 8捆绑在一起。它db位于JDK安装目录的目录中。

您可以从Apache Derby Downloads下载并安装Apache Derby 。

删除了JVM TI hprof代理

hprof代理程序库已被删除。

hprof剂被写为演示代码JVM工具界面,并没有打算成为一个生产工具。hprof代理的有用功能已被更好的替代方案所取代,包括JDK中包含的一些替代方案。

要以hprof格式创建堆转储,请使用诊断命令(jcmd)或jmap工具:

  • 诊断命令:。见。 jcmd <pid> GC.heap_dump`jcmd`
  • jmap : jmap -dump. 见jmap

对于CPU Profiler功能,请使用与JDK捆绑在一起的Java Flight Recorder。

注意:

Java Flight Recorder需要商业许可才能用于生产。要了解有关商业功能以及如何启用它们的更多信息,请访问http://www.oracle.com/technetwork/java/javaseproducts/

请参阅JEP 240:删除JVM TI hprof代理

删除了jhat工具

jhat工具是JDK 6中添加的实验性,不受支持的堆可视化工具。高级堆可视化器和分析器已经可用多年。

删除了java-rmi.exe和java-rmi.cgi启动器

java-rmi.exe来自Windows以及java-rmi.cgiLinux和Solaris 的启动程序已被删除。

java-rmi.cgi$JAVA_HOME/binLinux和Solaris上。

java-rmi.exe$JAVA_HOME/binWindows上。

这些启动程序被添加到JDK中以便于使用RMI CGI代理机制,该机制在JDK 8中已弃用。

多年来,使用servlet代替RMI over HTTP的替代方案已经可用,甚至是首选。请参阅Java RMI和对象序列化。

从JMX RMIConnector中删除了对IIOP传输的支持

来自JMX RMI连接器的IIOP传输支持及其支持类已从JDK中删除。

在JDK 8中,对IIOP传输的支持从需求降级为可选。这是多版本努力从JMX Remote API中删除对IIOP传输的支持的第一步。在JDK 9中,完全删除了对IIOP的支持。

公共API更改包括:

  • javax.management.remote.rmi.RMIIIOPServerImpl班已弃用。在调用时,它的所有方法和构造函数都会抛出java.lang.UnsupportedOperationException一条解释性消息。
  • 不会生成两个类,org.omg.stub.javax.management.rmi._RMIConnection_Stuborg.omg.stub.javax.management.rmi._RMIConnection_Tie

删除了Windows 32位客户端VM

Windows 32位客户端VM不再可用。仅提供服务器VM。

JDK 8及更早版本为Windows 32位系统提供了客户端JVM和服务器JVM。JDK 9及更高版本仅提供服务器JVM,该服务器JVM经过调整以最大化峰值运行速度。

删除了Java VisualVM

Java VisualVM是一个工具,它提供有关在Java虚拟机上运行的代码的信息。该jvisualvm工具提供了JDK 6,JDK 7和JDK 8。

Java VisualVM不再与JDK捆绑在一起,但您可以从VisualVM开源项目站点获取它。

删除了native2ascii工具

native2ascii工具已从JDK中删除。由于JDK 9及更高版本支持基于UTF-8的属性资源包,因此不再需要基于UTF-8的属性资源包到ISO-8859-1的转换工具。

UTF-8属性文件中的Java平台,标准版国际指南。

删除了特定于macOS的功能

本节包括从JDK 9开始已删除的特定于macOS的功能。

特定于平台的桌面功能

java.awt.Desktop类包含了苹果专用的API的替代品com.apple.eawtcom.apple.eio套餐。新API取代了macOS API,并且与平台无关。

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

com.apple.concurrentapple.applescript包没有任何替代删除。

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

删除了AppleScript引擎

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

AppleScript引擎在最近的版本中几乎无法使用。该功能仅适用于已在系统上具有Apple版本AppleScriptEngine.jar文件的系统上的JDK 7或JDK 8 。

下一步

在JDK 11上运行应用程序之后,这里有一些建议可以帮助您从Java SE平台中获得最大收益:

  • 如果需要,使用javac工具中的新-–release标志交叉编译到平台的旧版本 。
  • 利用IDE的建议,使用最新功能更新代码。
  • 通过运行静态分析工具jdeprscan,了解您的代码是否使用了弃用的API 。正如本指南中已经提到的,API可以从JDK中删除,但只能提前通知。
  • 熟悉多版本JAR文件等新功能(参见jar)。

文档可访问性

有关Oracle对辅助功能的承诺的信息,请访问Oracle辅助功能计划网站http://www.oracle.com/pls/topic/lookup?ctx=acc&id=docacc。

访问Oracle支持

已购买支持的Oracle客户可通过My Oracle Support获得电子支持。有关详细信息,请访问http://www.oracle.com/pls/topic/lookup?ctx=acc&id=info或访问http://www.oracle.com/pls/topic/lookup?ctx=acc&id=trs如果您听力受损。


Java平台,标准版Oracle JDK迁移指南,版本11

E94894-03

版权所有©2017,2019,Oracle和/或其附属公司。版权所有。

本指南将帮助您将应用程序从Oracle JDK 8迁移到Oracle JDK 10。

本软件及相关文档根据许可协议提供,该协议包含对使用和披露的限制,并受知识产权法保护。除非您的许可协议中明确允许或法律允许,否则您不得以任何形式使用,复制,复制,翻译,广播,修改,许可,传输,分发,展示,执行,发布或展示任何部分,或以任何方式。除非法律要求互操作性,否则禁止对该软件进行逆向工程,反汇编或反编译。

此处包含的信息如有更改,恕不另行通知,并且不保证没有错误。如果您发现任何错误,请以书面形式向我们报告。

如果这是交付给美国政府的软件或相关文档或代表美国政府许可的任何人,则以下通知适用:

美国政府最终用户:根据适用的联邦采购法规和代理机构,Oracle程序,包括任何操作系统,集成软件,安装在硬件上的任何程序和/或文档,都是“商业计算机软件”。具体的补充规定。因此,程序的使用,复制,公开,修改和调整,包括任何操作系统,集成软件,安装在硬件上的任何程序和/或文档,应受适用于程序的许可条款和许可限制的约束。 。没有其他权利授予美国政府。

该软件或硬件被开发用于各种信息管理应用中的一般用途。它不是为任何本质上危险的应用而开发或打算使用的,包括可能造成人身伤害风险的应用。如果您在危险应用程序中使用此软件或硬件,则您应负责采取所有适当的故障安全,备份,冗余和其他措施,以确保其安全使用。Oracle Corporation及其附属公司对因在危险应用中使用此软件或硬件而造成的任何损害不承担任何责任。

Oracle和Java是Oracle和/或其附属公司的注册商标。其他名称可能是其各自所有者的商标。

Intel和Intel Xeon是Intel Corporation的商标或注册商标。所有SPARC商标的使用均已获得许可,是SPARC International,Inc。的商标或注册商标.AMD,Opteron,AMD徽标和AMD Opteron徽标是Advanced Micro Devices的商标或注册商标。UNIX是The Open Group的注册商标。

该软件或硬件和文档可以提供对来自第三方的内容,产品和服务的访问或信息。除非您与Oracle之间的适用协议另有规定,否则Oracle Corporation及其附属公司不对第三方内容,产品和服务的任何形式的保证承担任何责任,并明确拒绝。Oracle Corporation及其附属公司对由于您访问或使用第三方内容,产品或服务而导致的任何损失,成本或损害不承担任何责任,但您与Oracle之间的适用协议中规定的除外。