耍酷的作业本 · yp1122.com域名whois查询-快推 ...· 4 周前 · |
星星上的斑马 · [百度云网盘6年级冀教版英语上册课程资料最新 ...· 1 月前 · |
大方的长颈鹿 · 普通高中和中职学校学生 ...· 3 月前 · |
眼睛小的热带鱼 · Python Flask: catch ...· 3 月前 · |
被表白的洋葱 · 科罗拉多急流足球俱乐部_搜狗百科· 4 月前 · |
There were significant changes made between the JDK 8 and later JDK releases.
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 and later 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.
Some APIs that have been made inaccessible, removed, or altered in their default behavior. You might encounter issues when compiling or running your application. See Removed Tools and Components and Security Updates .
The following sections describe the changes in the JDK package 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.
Changes to Internationalization
Strong Encapsulation in the JDK
When your application is running successfully on the latest version of JDK, review Next Steps , which will help you avoid problems with future releases.
See Java Platform, Standard Edition Internationalization Guide for more information about internationalization APIs and features of the Java SE Platform.
In JDK 18 and later, UTF-8 is the default charset used by Java SE APIs on all operating systems. See JEP 400: UTF-8 by Default . In contrast, in JDK 17 and earlier releases, the default charset is determined when the Java runtime starts, that is, on macOS, the default charset used to be UTF-8 except in the POSIX C locale. On other operating systems, it used to depend on the user's locale and the default encoding.
For example, on Windows, it's a codepage-based charset such as
windows-1252
or
windows-31j
. The method
java.nio.charsets.Charset.defaultCharset()
returns the default
charset.
java -XshowSettings:properties -version 2>&1 | grep native.encoding
If the encoding detected is different from UTF-8, then the application running in your environment may be affected.
Changing the JDK's Default Charset
file.encoding
to investigate further. Set its value on the
command line to one of the following:
UTF-8
: The default charset is UTF-8.
COMPAT
: The default charset is determined as
in JDK 17 and earlier releases.
java -Dfile.encoding=UTF-8
<your
application>
with the existing JDK. This will
provide the same environment as JDK 18 and later. Check if there are any
differences.
-Dfile.encoding=COMPAT
<your
application>
on JDK 18 and later to get the previous
behaviour, and check if there are any differences.
The
COMPAT
locale data provider, which represents the
locale data that is compatible with releases prior to JDK 9, is planned to be removed in a
future release.
See if your applications rely on
COMPAT
. Do this by
checking if the value
COMPAT
is specified in the system property
java.locale.providers
. If so, or you're migrating from JDK 8, then
test your applications with the latest JDK and the default
CLDR
locale
provider with respect to locale-related functions, such as the formatting and parsing of
dates, times, and numbers. If your tests yield unexpected results, then one workaround
is to provide your own SPI implementation. For example, the short month name for
September differs between
CLDR
and
COMPAT
in the UK
locale. The following SPI implementation addresses this incompatibility:
package spi;
import java.text.DateFormatSymbols;
import java.text.spi.DateFormatSymbolsProvider;
import java.util.Locale;
public class ShortMonthModifier extends DateFormatSymbolsProvider {
@Override
public DateFormatSymbols getInstance(Locale locale) {
assert locale.equals(Locale.UK);
return new DateFormatSymbols() {
@Override
public String[] getShortMonths() {
var ret = new DateFormatSymbols(Locale.UK).getShortMonths().clone();
ret[Calendar.SEPTEMBER] = "Sep";
return ret;
@Override
public Locale[] getAvailableLocales() {
return new Locale[]{Locale.UK};
}
Package this implementation as described in the section
Packaging of Locale Sensitive Service
Provider Implementations
in the
LocaleServiceProvider
JavaDoc API documentation. Afterward, place it on
the classpath and then run your applications with the
-Djava.locale.providers=SPI,CLDR
command-line option.
See JEP 252: Use CLDR Locale Data by Default .
Some tools and libraries use reflection to access parts of the JDK that are
meant for internal use only. This use of reflection negatively impacts the security and
maintainability of the JDK. To aid migration, JDK 9 through JDK 16 allowed this reflection
to continue, but emitted warnings about
illegal reflective access
. However, JDK 17
and later is
strongly encapsulated
, so this reflection is no longer permitted by
default. Code that accesses non-public fields and methods of
java.*
APIs
will throw an
InaccessibleObjectException
.
Note that the
sun.misc
and
sun.reflect
packages are available for reflection by tools and libraries in all JDK releases,
including JDK
22
.
The
java
launcher option
--illegal-access
allowed reflection to JDK internals in JDK 9 through JDK 16. You could specify the
following parameters:
--illegal-access=permit
: Allows code on the class path
to reflect over the internals of
java.*
packages that existed in
JDK 8. The first reflective-access operation to any such element causes a warning to
be issued, but no warnings are issued after that point.
--illegal-access=warn
: Causes a warning message to be issued for
each illegal reflective-access operation.
--illegal-access=debug
: Causes both a warning message and a stack
trace to be shown for each illegal reflective-access operation.
--illegal-access=deny
: Disables all illegal reflective-access
operations except for those enabled by other command-line options, such as
--add-opens
.
Many tools and libraries have been updated to avoid relying on JDK internals
and instead use standard Java APIs that were introduced between JDK 8 and 17. This means
the
--illegal-access
launcher option is obsolete in JDK 17. Any use of
this launcher option in JDK 17, whether with
permit
,
warn
,
debug
, or
deny
, will have
no effect other than to issue a warning message.
If you cannot obtain or deploy newer versions of tools and libraries, then there are two command-line options that enable you to grant access to specific internal APIs for older versions of tools and libraries:
--add-exports
: If you have an older tool or library that needs to
use an internal API that has been strongly encapsulated, then use the
--add-exports
runtime option. You can also use
--add-exports
at compile time to access the internal APIs.
--add-opens
: If you have an older tool or library that needs to
access non-public fields and methods of
java.*
APIs by reflection,
then use the
--add-opens
option.
See JEP 403: Strongly Encapsulate JDK Internals by Default .
If you have an older tool or library that needs to use an internal API that
has been strongly encapsulated, then use the
--add-exports
runtime option. You
can also use
--add-exports
at compile time to
access the internal APIs.
--add-exports
option
is:
--add-exports <source-module>/<package>=<target-module>(,<target-module>)*
where
<source-module>
and
<target-module>
are module names
and
<package>
is the
name of a package.
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.
<target-module>
is
ALL-UNNAMED
, then the source
package is exported to all unnamed modules, whether
they exist initially or are created later on. For
example:
--add-exports java.management/sun.management=ALL-UNNAMED
This
example allows code in all unnamed modules (code on
the class path) to access the public members of
public types in
java.management/sun.management
.
Note:
If the code on the class path uses the reflection API ( setAccessible(true) ) to attempt to access non-public fields and methods of
java.*
APIs, then the code
will fail. JDK 17 doesn't allow this by default. However, you can use the
--add-opens
option to allow this. See the section
--add-opens
for more information.
oldApp
that runs on the classpath must use the unexported
com.sun.jmx.remote.internal
package of the
java.management
module, then the access that it requires can be granted in this way:
--add-exports java.management/com.sun.jmx.remote.internal=ALL-UNNAMED
Add-Exports
JAR file manifest
attribute:
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 JEP 261: Module System .
Some tools and libraries use the reflection API
(
setAccessible(true)
) to attempt to access non-public
fields and methods of
java.*
APIs. This is no longer possible by
default on JDK 17, but you can use the
--add-opens
option on the
command line to enable it for specific tools and libraries.
--add-opens
is:
--add-opens <module>/<package>=<target-module>(,<target-module>)*
This
option allows
<module>
to open
<package>
to
<target-module>
, regardless of the
module declaration.
<target-module>
is
ALL-UNNAMED
, then the source package is exported to all unnamed
modules, whether they exist initially or are created later on. For
example:
--add-opens java.management/sun.management=ALL-UNNAMED
This
example allows all of the code on the class path to access nonpublic members of public
types in the
java.management/sun.management
package.
Note:
In a JNLP file for Java Web Start, you must include an equals sign between
--add-opens
and its
value.
<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.
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 and later 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:
$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 .
Significant changes have been made to the JDK and JRE.
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 and Later
JDK 11 and later 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 had 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 containing 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.
In JDK 9 and JDK 10, there are still separate JDK and JRE downloads, but each has the same directory structure. The JDK image contains the extra tools and libraries that have historically been found in the JDK. There are no
jdk/
versus
jre/
wrapper directories, and binaries (such as the
java
command) aren’t duplicated.
See JEP 220: Modular Run-Time Images .
JDK 9 and later releases maintain the hierarchy of class loaders that existed since the 1.2 release. However, the following changes have been made to implement the module system:
The application class loader is no longer an instance of URLClassLoader but, rather, of an internal class. It is the default loader for classes in modules that are neither Java SE nor JDK modules.
The extension class loader has been renamed; it is now the platform class loader. All classes in the Java SE Platform are guaranteed to be visible through the platform class loader.
Just because a class is visible through the platform class loader does not mean the class is actually defined by the platform class loader. Some classes in the Java SE Platform are defined by the platform class loader while others are defined by the bootstrap class loader. Applications should not depend on which class loader defines which platform class.
The changes that were implemented in JDK 9 may impact code that creates class
loaders with
null
(that is, the
bootstrap class loader) as the parent class loader
and assumes that all platform classes are visible
to the parent. Such code may need to be changed to
use the platform class loader as the parent (see
ClassLoader.getPlatformClassLoader
).
The platform class loader is not an instance of URLClassLoader , but, rather, of an internal class.
The bootstrap class loader is still built-in to the Java Virtual Machine and represented by
null
in the
ClassLoader
API. It defines the classes in a handful of critical modules, such as
java.base
. As a result, it defines far fewer classes than in JDK 8, so applications that are deployed with
-Xbootclasspath/a
or that create class loaders with
null
as the parent may need to change as described previously.
tools.jar
Class and resource files previously stored in
lib/rt.jar
,
lib/tools.jar
,
lib/dt.jar
and various other internal JAR files are stored in a more efficient format in implementation-specific files in the
lib
directory.
The removal of
rt.jar
and similar files leads to issues in these areas:
Starting from JDK 9,
ClassLoader.getSystemResource
doesn’t return a URL
pointing to a JAR file (because there are no JAR files). Instead, it returns a
jrt
URL, which names the modules, classes, and resources
stored in a runtime image without revealing the internal structure or format of
the image.
For example:
ClassLoader.getSystemResource("java/lang/Class.class");
When run on JDK 8, this method returns a JAR URL of the form:
jar:file:/usr/local/jdk8/jre/lib/rt.jar!/java/lang/Class.class
which embeds a file URL to name the actual JAR file within the runtime image.
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.
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:
<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 .
The
java.endorsed.dirs
system property and the
lib/endorsed
directory are no longer present. The
javac
compiler 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:
<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.
You’ll see a similar error if the
java.endorsed.dirs
system property is set.
To fix this error, remove the
lib/endorsed
directory, or unset the
java.endorsed.dirs
system property.
See JEP 220: Modular Run-Time Images .
This section includes macOS-specific features that have been removed, starting in JDK 9.
The
java.awt.Desktop
class contains replacements for the APIs in the Apple–specific
com.apple.eawt
and
com.apple.eio
packages. The new APIs supersede the macOS APIs and are platform-independent.
The APIs in the
com.apple.eawt
and
com.apple.eio
packages are encapsulated, so you won’t be able to compile against them in JDK 9 or later releases. However, they remain accessible at runtime, so existing code that is compiled to old versions continues to run. Eventually, libraries or applications that use the internal classes in the
apple
and
com.apple
packages and their subpackages will need to migrate to the new API.
The
com.apple.concurrent
and
apple.applescript
packages are removed without any replacement.
See JEP 272: Platform-Specific Desktop Features.
The AppleScript engine, a platform-specific javax.script implementation, has been removed without any replacement in the JDK.
The AppleScript engine has been mostly unusable in recent releases. The functionality worked only in JDK 7 or JDK 8 on systems that already had Apple's version of the
AppleScriptEngine.jar
file on the system.
The Java 11 and later installer creates Windows registry keys when installing the JDK. For JDK 18, the installer creates the following Windows registry keys:
“HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK”
“HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK\18”
If two versions of the JDK are installed, then two different Windows registry keys are created. For example, if JDK 17.0.1 is installed with JDK 18, then the installer creates the another Windows registry key as shown:
“HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK”
“HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK\18”
“HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK\17.0.1”
Java deployment technologies were deprecated in JDK 9 and removed in JDK 11.
Use the
jlink
tool introduced with JDK 9 to package and deploy dedicated runtimes rather than relying on a pre-installed system JRE.
The ability to request a version of the JRE that isn’t the JRE being launched at launch time is removed, starting in JDK 9.
Modern applications are typically deployed using Java Web Start (JNLP), native OS packaging systems, or active installers. These technologies have their own methods to manage the JREs needed, by finding or downloading and updating the required JRE, as needed. This makes the launcher's launch-time JRE version selection obsolete.
In the previous releases, you could specify what JRE version (or range of versions) to use when starting an application. Version selection was possible through both a command-line option and manifest entry in the application's JAR file.
java
launcher is modified as follows:
-version:
option is given on the command line.
JRE-Version
manifest entry is found in a JAR file.
&
instead of
&
in JNLP files.
The JNLP file syntax conforms to the XML specification and all JNLP files should be able to be parsed by standard XML parsers.
JNLP files let you specify complex comparisons. Previously, this was done by using the ampersand (
&
), but this isn’t supported in standard XML. If you’re using
&
to create complex comparisons, then replace it with
&
in your JNLP file.
&
is compatible with all versions of JNLP.
Comparing numeric version element types against nonnumeric version element types.
Previously, when an
int
version element was compared with another version element that couldn’t be parsed as an
int
, the version elements were compared lexicographically by ASCII value.
If the element that can be parsed as an
int
is a shorter string than
the other element, it will be padded with leading zeros before being compared
lexicographically by ASCII value. This ensures there can be no circularity.
In the case where both version comparisons and a JNLP servlet are used, you should use only numeric values to represent versions.
java
(or
j2se
) elements.
This is permitted in the specification. It was previously supported, but this support wasn’t reflected in the specification.
The JNLP specification has been enhanced to add a
type
attribute to
application-desc
element, and add the subelement
param
in
application-desc
(as it already is in
applet-desc
).
This doesn’t cause problems with existing applications because the previous way of specifying a JavaFX application is still supported.
See the JNLP specification updates at JSR-056 .
This section describes changes to garbage collection starting in JDK 9.
The Garbage-First Garbage Collector (G1 GC) is the default garbage collector in JDK 9 and later releases.
A low-pause collector such as G1 GC should provide a better overall experience, for most users, than a throughput-oriented collector such as the Parallel GC, which is the JDK 8 default.
See Ergonomic Defaults for G1 GC and Tunable Defaults in Java Platform, Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide for more information about tuning G1 GC.
DefNew + CMS
ParNew + SerialOld
Incremental CMS
The foreground mode for CMS has also been removed. The command-line flags that were removed are
-Xincgc
,
-XX:+CMSIncrementalMode
,
-XX:+UseCMSCompactAtFullCollection
,
-XX:+CMSFullGCsBeforeCompaction
, and
-XX:+UseCMSCollectionPassing
.
The command-line flag
-XX:+UseParNewGC
no longer has an effect. The
ParNew
flag can be used only with CMS and CMS requires
ParNew
. Thus, the
-XX:+UseParNewGC
flag has been deprecated and is eligible for removal in a future release.
See JEP 214: Remove GC Combinations Deprecated in JDK 8 .
Note:
The CMS garbage collector has been removed. See JEP 363: Remove the Concurrent Mark Sweep (CMS) Garbage Collector .Removed Permanent Generation
The permanent generation was removed in JDK 8, and the related VM options cause a warning to be printed. You should remove these options from your scripts:
-XX:MaxPermSize=
size
-XX:PermSize=
size
Java HotSpot(TM) 64-Bit Server VM warning: Ignoring option MaxPermSize; support was removed in 8.0
Tools that are aware of the permanent generation may have to be updated.
See JEP 122: Remove the Permanent Generation and JDK 9 Release Notes - Removed APIs, Features, and Options .
Garbage collection (GC) logging uses the JVM unified logging framework, and there are some differences between the new and the old logs. Any GC log parsers that you’re working with will probably need to change.
You may also need to update your JVM logging options. All GC-related logging should use the
gc
tag (for example,
—Xlog:gc
), usually in combination with other tags. The
—XX:+PrintGCDetails
and
-XX:+PrintGC
options have been deprecated.
See Enable Logging with the JVM Unified Logging Framework in the Java Development Kit Tool Specifications and JEP 271: Unified GC Logging .
If you still rely on applets, it might be possible to launch them on Windows systems by using JRE 8 with Microsoft Edge in Internet Explorer mode. See Microsoft Edge + Internet Explorer mode: Getting Started guide .
As of September 2021, the Java Plugin required to launch Applets, remains updated on Windows in Java 8 but may be removed at any time in a future update release.
Oracle Customers can find more information at My.Oracle.Support Note 251148.1 - Java SE 8 End of Java Plugin Support (requires login).
The
java.util.regex.Pattern
class defines character classes
in regular expressions with square brackets. For example,
[abc]
matches
a,b
, or
c
. Negated character classes are
defined with a caret immediately following the opening square brace. For example,
[^abc]
matches any character except
a,b
,
or
c
.
In JDK 8 and earlier, negated character classes did not negate nested character
classes. For example,
[^a-b[c-d]e-f]
matches
c
but does not match
a
or
e
as they are not within the nested class.
The operators are applied one after another. In this example, the
negation operator
^
is applied before nesting. In
JDK 8 and earlier, the operator
^
was applied only
to the outermost characters in the character class but
not
to
nested character classes. This behaviour was confusing and difficult
to understand.
However, in JDK 9 and later, the negation operator was
applied to all nested character classes. For example,
[^a-b[c-d]e-f]
does not match
[^a-d&&c-f]
In JDK 8, the
^
operator is applied first,
hence this example is interpreted as
[^a-d]
intersected with
[c-f]
. This matches
e
and
f
but not
a
,
b
,
c
,
or
d
.
In JDK 9 and later, the
&&
operator
is applied first, hence this example is interpreted as the
complement of
[a-d]&&[c-f]
. This matches
a
,
b
,
e
,
and
f
but not
c
or
As a best practice, look for regular expressions that use character classes with some combination of negation, intersection, and nested classes. These regular expressions may need to be adjusted to account for the changed behavior.
In JDK 17, the Security Manager and APIs related to it have been deprecated and are subject to removal in a future release. There is no replacement for the Security Manager. See JEP 411 for discussion and alternatives.
Finalization has been deprecated for removal in JDK 18.
The use of finalization is discouraged. It can lead to problems with security, performance, and reliability. See JEP 421: Deprecate Finalization for Removal .