6
Compatibility challenges when moving to Java 9 or later

This chapter covers

  • Why JEE modules are deprecated and not resolved by default
  • Compiling and running code that depends on JEE modules
  • Why casts to URLClassLoader fail
  • Understanding the new JDK run-time image layout
  • Replacing the removed extension mechanism, endorsed standards override mechanism, and boot class path option

This chapter and chapter 7 discuss compatibility challenges when migrating an existing code base to Java 9 and beyond. You won’t be creating any modules yet; these chapters are about building and running an existing project on the newest release.

Why does moving to Java 9+ require two entire chapters? Can’t you install the newest JDK and expect everything to just work? Isn’t Java meant to be backward-compatible? Yes—if your project, including its dependencies, only relies on nondeprecated, standardized, documented behavior. But that’s a big if, and it turns out that in the absence of any enforcement, the wider Java community has strayed from that path.

As you’ll see in this chapter, the module system deprecated some Java features, removed others, and changed some internals:

  • Modules containing JEE APIs are deprecated and need to be resolved manually (section 6.1).
  • The application class loader (also called the system class loader) is no longer a URLClassLoader, which breaks some casts (section 6.2).
  • The directory layout of the Java run-time image (JRE and JDK) was overhauled (section 6.3)
  • A number of mechanisms like compact profiles and the endorsed-standards override mechanisms were removed (section 6.4).
  • A few smaller things were changed, too, like no longer allowing the single underscore as an identifier (section 6.5).

That’s not all, though. Chapter 7 discusses two more challenges (internal APIs and split packages). They got their own chapter because chances are you’ll encounter them again with non-JDK modules after you’ve migrated your project.

Taken together, these changes break some libraries, frameworks, tools, techniques, and maybe your code, too, so unfortunately updating to Java 9+ isn’t always an easy task. Generally speaking, the larger and older the project, the higher the chances it will take some work. Then again, it’s usually well-invested time, because it’s an opportunity to pay back some technical debt and get the code base into better shape.

By the end of this chapter and the next, you’ll know the challenges of updating to Java 9, 10, and 11 or even later. Given an application, you’ll be able to make informed guesses about what needs to be done; and assuming all your dependencies play along, you’ll be able to make it work on the newest release. You’ll also be well prepared for chapter 9, which discusses strategies for migrating to Java 9 and later.

6.1 Working with JEE modules

A lot of code in Java SE is related to Java EE / Jakarta EE (which I abbreviate as JEE): CORBA comes to mind, and so do Java Architecture for XML Binding (JAXB) and Java API for XML Web Services (JAX-WS). These and other APIs ended up in the six modules shown in table 6.1. This could be nothing more than a small side note and the end of the story, but unfortunately it’s not. When you try to compile or run code that depends on a class from these modules, the module system will claim the modules are missing from the graph.

Here’s a compile error on Java 9 for a class using JAXBException from the java.xml.bind module:

> error: package javax.xml.bind is not visible
> import javax.xml.bind.JAXBException;
>                 ^
>     (package javax.xml.bind is declared in module java.xml.bind,
>      which is not in the module graph)
> 1 error

If you get it past the compiler but forget to massage the runtime, you’ll get a NoClassDefFoundError:

> Exception in thread "main" java.lang.NoClassDefFoundError:
>         javax/xml/bind/JAXBException
>     at monitor.Main.main(Main.java:27)
> Caused by: ClassNotFoundException:
>         javax.xml.bind.JAXBException
>     at java.base/BuiltinClassLoader.loadClass
>         (BuiltinClassLoader.java:582)
>     at java.base/ClassLoaders$AppClassLoader.loadClass
>         (ClassLoaders.java:185)
>     at java.base/ClassLoader.loadClass
>         (ClassLoader.java:496)
>     ... 1 more

What’s going on? Why are properly standardized Java APIs not present for code on the class path, and what can be done about that?

Table 6.1 The six JEE modules. The descriptions cite the documentation.
Module name Description Packages
java.activation Defines the JavaBeans Activation Framework (JAF) API javax.activation
java.corba Defines the Java binding of the Open Management Group (OMG) CORBA APIs, and the RMI-IIOP API javax.activity, javax.rmi, javax.rmi.CORBA, org.omg.*
java.transaction Defines a subset of the Java Transaction API (JTA) to support CORBA interop javax.transaction
java.xml.bind Defines the JAXB API javax.xml.bind.*
java.xml.ws Defines the JAX-WS and Web Services Metadata APIs javax.jws, javax.jws.soap, javax.xml.soap, javax.xml.ws.*
java.xml.ws.annotation Defines a subset of the Common Annotations API to support programs running on the Java SE platform javax.annotation

6.1.1 Why are the JEE modules special?

Java SE contains a few packages that consist of endorsed standards and standalone technologies. These technologies are developed outside the Java Community Process (JCP), often because they rely on standards governed by other bodies. Examples are the Document Object Model (DOM), developed by the World Wide Web Consortium (W3C) and the Web Hypertext Application Technology Working Group (WHATWG), and Simple API for XML (SAX). If you’re interested, you can find a list of them and the packages they’re in at http://mng.bz/8Ek7. Disproportionately many of them fall into the JEE modules listed in table 6.1: java.corba, java.xml.bind, and java.xml.ws.

Historically, the Java Runtime Environment (JRE) shipped with implementations of these technologies but was ready to let users upgrade them independently of the JRE. This could be done with the endorsed standards override mechanism (see section 6.5.3).

Similarly, application servers often extend or upgrade the CORBA, JAXB, or JAX-WS APIs as well as the JavaBeans Activation Framework (in java.activation) or the JTA (in java.transaction) by providing their own implementations. Finally, java.xml.ws.annotation contains the javax.annotation package. It’s often extended by the various JSR 305 implementations, which are most famous for their null-related annotations.

In all these cases of extending or replacing APIs that ship with Java, the trick is to use the exact same package and class names, so the classes are loaded from an external JAR instead of the built in ones. In the parlance of the module system, this is called a split package: the same package is split across different modules or a module and the class path.

This is a general mechanism for all packages of all modules: splitting them between a module and the class path makes the class-path portion invisible. What makes the six JEE modules special is that unlike other modules, it’s customary to extend or upgrade them with the split-package approach.

To keep application servers and libraries like the JSR 305 implementations working without extensive configuration, a trade-off was made: for code on the class path, Java 9 and 10 by default don’t resolve the JEE modules, meaning they don’t make it into the module graph and hence aren’t available (see section 3.4.3 for unresolved modules and section 8.2.2 for details of the class path scenario).

That works well for applications that come with their own implementations of these JEE APIs, but not so much for those that relied on the JDK variants. Without further configuration, code on the class path using types from those six modules will fail to compile and run.

To get rid of this complexity and to properly separate Java SE from JEE, these modules are deprecated in Java 9 and removed in Java 11. With their removal, command-line tools like wsgen and xjc are also no longer shipped with the JDK.

6.1.2 Manually resolving JEE modules

What do you do if you get a compile or run-time error due to missing JEE APIs, or if a JDeps analysis (see appendix D) shows that you depend on JEE modules? There are three answers:

  • If your application runs in an application server, it may provide an implementation of those APIs, in which case you shouldn’t encounter run-time errors. Depending on your setup, you may have to fix build errors, though—either of the other two solutions should do that.
  • Pick a third-party implementation of that API, and add it as a dependency to your project. Because JEE modules aren’t resolved by default, that implementation is used during compilation and at run time without problems.
  • On Java 9 and 10, add the platform module with --add-modules as described in section 3.4.3. Because the JEE modules are removed in Java 11, this won’t work there.

The example at the beginning of the section tried to use JAXBException from the java.xml.bind module. Here’s how to make that module available for compilation with --add-modules:

$ javac
    --class-path ${jars}
    --add-modules java.xml.bind
    -d ${output-dir}
    ${source-files}

When the code is compiled and packaged, you need to add the module again for execution:

$ java
    --class-path ${jars}
    --add-modules java.xml.bind
    ${main-class}

If you depend on a few of the JEE APIs, it may be easier to add the java.se.ee module instead of each individual module. It makes all six EE modules available, which simplifies things a bit. (How does it make them available? Read about aggregator modules in section 11.1.5.)

The effort of manually adding JEE modules is only required for unmodularized code. Once it’s modularized, the EE modules stop being special: you can require them like any other module, and they will be resolved like any other module—at least, until they’re removed.

6.1.3 Dropping in third-party implementations of JEE modules

Maybe you’ve been using the endorsed standards override mechanism to update standards and standalone technologies. In that case, you may wonder what happened to it in a time of modules. As you may have guessed, it was removed and replaced by something new.

Both the compiler and runtime offer the --upgrade-module-path option, which accepts a list of directories, formatted like the ones for the module path. When the module system creates the module graph, it searches those directories for artifacts and uses them to replace upgradeable modules. The six JEE modules are always upgradeable:

  • java.activation
  • java.corba
  • java.transaction
  • java.xml.bind
  • java.xml.ws
  • java.xml.ws.annotation

JDK vendors may make more modules upgradeable. On Oracle JDK, for example, this applies to java.jnlp. Furthermore, application modules that were linked into an image with jlink are always upgradeable—see section 14.2.1 for more on that.

JARs on the upgrade module path don’t have to be modular. If they lack a module descriptor, they’ll be turned into automatic modules (see section 8.3) and can still replace Java modules.

6.2 Casting to URLClassLoader

Running a project on Java 9 or later, you may encounter a class-cast exception like the one shown in the following example. Here, the JVM complains that it couldn’t cast an instance of jdk.internal.loader.ClassLoaders.AppClassLoader to URLClassLoader:

> Exception in thread "main" java.lang.ClassCastException:
>     java.base/jdk.internal.loader.ClassLoaders$AppClassLoader  
>     cannot be cast to java.base/java.net.URLClassLoader  
>         at monitor.Main.getClassPathContent(Main.java:46)
>         at monitor.Main.main(Main.java:28)

What’s this new type, and why does it break the code? Let’s find out! In the process, you’ll learn how Java 9 changes class-loading behavior to improve launch performance. So even if your project doesn’t suffer from this particular problem, it’s still a great opportunity to deepen your Java knowledge.

6.2.1 Application class loaders, then and now

In all Java versions, the application class loader (often called the system class loader) is one of three class loaders the JVM uses to run an application. It loads JDK classes that don’t need any special privileges as well as all application classes (unless the app uses its own class loaders, in which case none of the following applies).

You can access the application class loader by calling ClassLoader.getSystemClassLoader() or by calling getClass().getClassLoader() on an instance of one of your classes. Both methods promise to give you an instance of type ClassLoader. On Java 8 and before, the application class loader is a URLClassLoader, a subtype of ClassLoader; and because URLClassLoader offers some methods that can come in handy, it’s common to cast the instance to it. You can see an example of that in listing 6.1.

Without modules as a run-time representation of JARs, URLClassLoader has no idea in which artifact to find a class; as a consequence, whenever a class needs to be loaded, URLClassLoader scans every artifact on the class path until it finds what it’s looking for (see figure 6.1). That’s obviously pretty ineffective.

Listing 6.1 Casting the application class loader to URLClassLoader

private String getClassPathContent() {
    URLClassLoader loader =
        (URLClassLoader) this.getClass().getClassLoader();  
    return Arrays.stream(loader.getURLs())  
            .map(URL::toString)
            .collect(joining(", "));
}
c06_01.png

Figure 6.1 Without modules (top), a particular class is loaded by scanning all artifacts on the class path. With modules (bottom), the class loader knows which modular JAR a package comes from and loads it directly from there.

Now let’s turn to Java 9+. With JARs getting a proper representation at run time, the class-loading behavior could be improved: when a class needs to be loaded, the package it belongs to is identified and used to determine a specific modular JAR. Only that JAR is scanned for the class (see figure 6.1). This relies on the assumption that no two modular JARs contain types in the same package—if they do, it’s called a split package, and the module system throws an error as section 7.2 explains.

The new type AppClassLoader and its equally new supertype BuiltinClassLoader implement the new behavior, and from Java 9 on, the application class loader is an AppClassLoader. That means the occasional (URLClassLoader) getClass().getClassLoader() sequence will no longer execute successfully. If you want to learn more about the structure and relationships of class loaders in Java 9+, take a look at section 12.4.1.

6.2.2 Getting by without URLClassLoader

If you encounter a cast to URLClassLoader in a project you depend on and there’s no Java 9+-compatible version to update to, you can’t do much except one of the following:

  • Open an issue with the project, or contribute a fix.
  • Fork or patch the project locally.
  • Wait.

If push came to shove, you could switch to another library or framework if it had versions that run fine on Java 9+.

If your own code does the casting, you can (and have to) do something about it. Unfortunately, chances are you may have to give up a feature or two. It’s likely you cast to URLClassLoader to use its specific API, and although there have been additions to ClassLoader, it can’t fully replace URLClassLoader. Still, have a look—it may do the thing you want.

If you just need to see the class path an application was launched with, check the system property java.class.path. If you’ve used URLClassLoader to dynamically load user-provided code (for example, as part of a plugin infrastructure) by appending JARs to the class path, then you have to find a new way to do that, because it can’t be done with the application class loader used by Java 9 and later versions.

Instead, consider creating a new class loader—which has the added advantage that you’ll be able to get rid of the new classes, because they aren’t loaded into the application class loader. If you’re compiling at least against Java 9, layers could be an even better solution (see section 12.4).

You may be tempted to investigate AppClassLoader and use its abilities if it does what you need. Generally speaking, don’t! Relying on AppClassLoader is ugly because it’s a private inner class, so you have to use reflection to call it. Relying on its public supertype BuiltinClassLoader isn’t recommended, either.

As the package name jdk.internal.loader suggests, it’s an internal API; and because the package was added in Java 9, it isn’t available by default, so you’d have to use --add-exports or even --add-opens (see section 7.1 for details). This not only complicates the code and build process, it also exposes you to possible compatibility problems on future Java updates—for example, when these classes are refactored. So don’t do it unless it’s absolutely necessary to implement a mission-critical feature.

6.2.3 Finding troublesome casts

Examining the code for these casts is simple: a full-text search for “(URLClassLoader)” should do it and contain few false positives (include the parentheses to only find casts). As for finding them in your dependencies, I don’t know of any tool that make that process comfortable. I guess a combination of build-tool magic (to get all your dependencies’ source JARs in one place), command-line sorcery (to access all their .java files and their file content), and yet another full-text search could do the trick.

6.3 Updated run-time image directory layout

The JDK’s and JRE’s directory structures evolved incrementally, and it shouldn’t be surprising that over the course of more than 20 years, they collected dust. One reason for not reorganizing them over time was, of course, backward compatibility. As is true for seemingly every detail, some code depends on their specific layout. Two examples:

  • Some tools, particularly IDEs, depend on the exact location of rt.jar (the classes making up the core Java runtime), tools.jar (support classes for tools and utilities), and src.zip (the JDK source code).
  • There exists code that searches for Java commands like javac, jar, or javadoc by speculating that the running JRE has a sibling directory bin containing them—which is true if the JRE is part of a JDK install, because that contains a bin folder with those commands and a jre folder next to each other.

Then came the module system, which broke with the basic assumptions that made these two examples possible:

  • The JDK code is now modularized and should hence be delivered in individual modules instead of monolithic JARs like rt.jar and tools.jar.
  • With a modularized Java code base and a tool like jlink, run-time images can be created from any set of modules.

Starting with Java 11, there is no longer a standalone JRE package. Running a program requires either a JDK or a package created by jlink.

As it became clear the module system would incur some breaking changes, the decision was made to go all the way and completely reorganize the run-time image directory structure. You can see the resulting changes in figure 6.2. Overall, the new layout is much simpler:

  • A single bin directory and no duplicate binaries
  • A single lib directory
  • A single directory, conf, to contain all files meant for configuration
c06_02.png

Figure 6.2 Comparison of the directory structure of JDK 8 and 9. The new one is much cleaner.

The most immediate consequence of these changes is that you need to update your development tools, because old versions likely won’t work with JDK installs of version 9 and later. Depending on the project, it may make sense to search it for code that rummages around in the JDK/JRE folder to look up binaries, property files, or anything else.

The URL you get for system resources, for example from ClasLoader::getSystemResource, has also changed. It used to be of the following form, where ${path} is something like java/lang/String.class:

jar:file:${java-home}/lib/rt.jar!${path}

It now looks like this:

jrt:/${module}/${path}

All JDK APIs that create or consume such URLs operate on the new schema, but non-JDK code handcrafting these URLs must be updated for Java 9+.

Furthermore, the Class::getResource* and ClassLoader::getResource* methods no longer read JDK-internal resources. Instead, to access module-internal resources, use Module::getResourceAsStream or create a JRT file system as follows:

FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
fs.getPath("java.base", "java/lang/String.class"));

For more details on how to access resources, see section 5.2.

6.4 Selecting, replacing, and extending the platform

When compiling code or launching the JVM, there used to be various ways to specify which classes constitute the JDK platform. You could select a subset of the JDK, replace a specific technology (like JAXB) with another, add a few classes, or pick an entirely different platform version to compile against or launch with. The module system made some of these features obsolete and reimplemented others with a more modern approach; and regardless of the JPMS, the Java 9 release removes a few more.

If you’re relying on one or more of the features discussed in this section, you’ll have to put in some work to keep your project running. Nobody likes to be forced into reworking something that doesn’t cause any apparent problems, but looking over these features (most of which I never used), I can only imagine how much simpler the JDK internals became without them.

6.4.1 No more compact profiles

As section 1.5.5 explains, one goal of the module system was to allow users to create a run-time image with only the modules they need. This is particularly interesting for small devices with limited storage and for virtualizing environments, because both are interested in small run-time images. When it became apparent the module system wouldn’t be released with Java 8, which was the plan for a while, compact profiles were created as an interim solution.

The three compact profiles define subsets of the Java SE 8 API and JREs with just the required classes to support those API subsets. After picking a profile that matches your application’s requirements, you’d use the javac option -profile to compile against it (to make sure you stay within the selected subset) and then run the bytecode on the matching variant.

With the module system in play, much more flexible run-time images can be created with jlink (see section 14.1), and compact profiles are no longer needed. The Java 9+ compiler will hence only accept -profile if compiling for Java 8. To compile against a specific selection of modules, you can use the --limit-modules option, as explained in section 5.3.5.

These are the modules you need to get the same APIs as the three compact profiles:

  • For the compact1 profilejava.base, java.logging, and java.scripting
  • For the compact2 profile —Those for compact1 plus java.rmi, java.sql, and java.xml
  • For the compact3 profile —Those for compact2 plus java.compiler, java.instrument, java.management, java.naming, java.prefs,java.security.jgss, java.security.sasl, java.sql.rowset, and java.xml.crypto

Instead of relying on a fixed selection, I recommend a different approach. Use jlink to create an image with only the platform modules you need (see section 14.1); if your application and its dependencies are fully modularized, you can even include your application modules (see section 14.2).

6.4.2 Extension mechanism removed

Before Java 9, the extension mechanism let us add classes to the JDK without having to place them on the class path. It loaded them from various directories: from directories named by the system property java.ext.dirs, from lib/ext in the JRE, or from a platform-specific system-wide directory. Java 9 removes this feature, and the compiler and runtime will exit with an error if the JRE directory exists or the system property is set.

Alternatives are as follows:

  • The java and javac option --patch-module injects content into modules (see section 7.2.4).
  • The java and javac option --upgrade-module-path replaces an upgradeable platform module with another one (see section 6.1.3).
  • The extending artifacts can be placed on the class path.

6.4.3 Endorsed standards override mechanism removed

Before Java 9, the endorsed standards override mechanism let us replace certain APIs with custom implementations. It loaded them from the directories named by the system property java.endorsed.dirs or the lib/endorsed directory in the JRE. Java 9 removes this feature, and the compiler and runtime will exit with an error if the JRE directory exists or the system property is set. The alternatives are the same as for the extension mechanism (section 6.4.2).

6.4.4 Some boot class path options removed

The -Xbootclasspath and -Xbootclasspath/p options were removed. Use the following options instead:

  • The javac option --system specifies an alternate source of system modules.
  • The javac option --release specifies an alternate platform version.
  • The java and javac option --patch-module injects content into modules in the initial module graph.

6.4.5 No compilation for Java 5

The Java compiler can process sources from various Java language versions (for example, Java 7, specified with -source) and can likewise produce bytecode for various JVM versions (for example, for Java 8, specified with -target). Java used to follow a "one plus three back" policy, which means javac 9 supports Java 9 (obviously) as well as 8, 7, and 6.

Setting -source 5 or -target 5 on javac 8 leads to a deprecation warning and is no longer supported by javac 9. Similarly, setting -source 6 or -target 6 on Java 9 results in the same warning. Now that there are releases every six months, this policy no longer applies. Java 10, 11, and 12 can compile for Java 6 just fine.

6.4.6 JRE version selection removed

Before Java 9, you could use the -version:N option on java (or the corresponding manifest entry) to launch the application with a JRE of version N. In Java 9, the feature was removed: the Java launcher quits with an error for the command-line option and prints a warning for the manifest entry while otherwise ignoring it. If you’ve been relying on that feature, here’s what the Java documentation has to say about that:

Modern applications are typically deployed via 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.

Looks like the docs think applications using -version:N aren’t modern—what a rude thing to say. Joking aside, if your application depended on that feature, you have no other option but to make it work without -version:N; for example, by bundling it with the JRE it works best on.

6.5 Little things that make big things fail

In addition to the larger challenges posed by the module system, there are a few changes, often not related to the JPMS, that are smaller but will cause trouble all the same:

  • New format for version strings
  • Removal of a number of JDK and JRE tools
  • Single underscore no longer a valid identifier
  • Java Network Launch Protocol (JNLP) syntax update
  • Removal of JVM options

I don’t want to keep you too long, but I also don’t want to leave out something that stops your migration dead in its tracks. So I’ll address each of these but be quick about it.

6.5.1 New version strings

After more than 20 years, Java has finally and officially accepted that it’s no longer on version 1.x. About time. From now on, the system property java.version and its siblings java.runtime.version, java.vm.version, java.specification.version, and java.vm.specification.version no longer start with 1.x but with x. Similarly, java -version returns x, so on Java 9 you get 9.something.

An unfortunate side effect is that version-sniffing code may suddenly stop reporting the correct results, which could lead to weird program behavior. A full-text search for the involved system properties should find such code.

As for updating it, if you’re willing to raise a project’s requirements to Java 9+, you can eschew the system property prodding and parsing and instead use the new Runtime.Version type, which is much easier:

Version version = Runtime.version();
// on Java 10 and later, use `version.feature()`
switch (version.major()) {
    case 9:
        System.out.println("Modularity");
        break;
    case 10:
        System.out.println("Local-Variable Type Inference");
        break;
    case 11:
        System.out.println("Pattern Matching (we hope)");
        break;
}

6.5.2 Tool exodus

The JDK accrued a lot of tools, and over time some became superfluous or were superseded by others. Some were included in Java 9’s spring cleaning:

  • JavaDB is no longer included. It was an Apache Derby DB, which you can download from https://db.apache.org.
  • VisualVM is no longer bundled with the JDK and became a standalone project at https://github.com/oracle/visualvm.
  • The hprof agent library has been removed. Tools replacing its features are jcmd, jmap, and the Java Flight Recorder.
  • The jhat heap visualizer was removed.
  • The java-rmi.exe and java-rmi.cgi launchers were removed. As an alternative, use a servlet to proxy RMI over HTTP.
  • The native2ascii tool was used to convert UTF-8–based property resource bundles to ISO-8859-1. Java 9+ supports UTF-8 based bundles, though, so the tool became superfluous and was removed.

Furthermore, all JEE-related command-line tools like wsgen and xjc are no longer available on Java 11 because they were removed together with the modules containing them (see section 6.1 for details on JEE modules).

6.5.3 The littlest things

Here comes probably the littlest thing that can make your Java 9 build fail: Java 8 deprecated the single underscore _ as an identifier, and on Java 9 you get a compile error when using it as one. This was done to reclaim the underscore as a possible keyword; future Java versions will give it special meaning.

Another issue: Thread.stop(Throwable) now throws an UnsupportedOperationException. The other stop overloads continue to work, but using them is highly discouraged.

The JNLP syntax has been updated to conform with the XML specification and “to remove inconsistencies, make code maintenance easier, and enhance security.” I won’t list the changes—you can find them at http://mng.bz/dnfM.

Each Java version removes some deprecated JVM options, and Java 9 is no different. It has a particular focus on garbage collection, where a few combinations are no longer supported (DefNew + CMS, ParNew + SerialOld, Incremental CMS) and some configurations were removed (-Xincgc, -XX:+CMSIncrementalMode, -XX:+UseCMSCompactAtFullCollection, -XX:+CMSFullGCsBeforeCompaction, -XX:+UseCMSCollectionPassing) or deprecated (-XX:+UseParNewGC). Java 10, in turn, removes -Xoss, -Xsqnopause, -Xoptimize, -Xboundthreads, and -Xusealtsigs.

6.5.4 New deprecations in Java 9, 10, and 11

Finally, here’s a non-exhaustive list of things that are deprecated in Java 9, 10, and 11:

  • The Applet API in the java.applet package, together with the appletviewer tool and the Java browser plugin
  • Java Web Start, JNLP, and the javaws tool
  • The Concurrent Mark Sweep (CMS) garbage collector
  • The HotSpot FlatProfiler, activated with -Xprof
  • The policytool security tool

Java 10 and 11 already followed through on some of the deprecations:

  • Java 10 removes FlatProfiler and policytool.
  • Java 11 removes the Applet API and Web Start.

For more, as well as for details and suggested alternatives, check the release notes (Java 9: http://mng.bz/GLkN; Java 10: http://mng.bz/zLeV) and the list of deprecated code that’s marked for removal (Java 9: http://mng.bz/YX9e; Java 10: http://mng.bz/qRoU).

Summary

  • JEE modules are deprecated in Java 9 and removed in Java 11. You need to find a third-party dependency that fulfills your requirements sooner rather than later.
  • In Java 9 and 10, these modules aren’t resolved by default, which can lead to compile-time and run-time errors. To fix this, either use a third-party dependency that implements the same API or make the JEE module available with --add-modules.
  • The application class loader is no longer of type URLClassLoader, so code like (URLClassLoader) getClass().getClassLoader() fails. Solutions are to only rely on the ClassLoader API, even if that means a feature must be removed (recommended); create a layer to dynamically load new code (recommended); or hack into the class-loader internals and use BuiltinClassLoader or even AppClassLoader (not recommended).
  • The directory structure of the run-time image changed, and you likely have to update your tools, particularly IDEs, to work with Java 9 and later. Code rattling around in JDK/JRE directories or handcrafting URLs for system resources needs to be updated, too.
  • Several mechanisms that modified the set of classes constituting the platform were removed. For most of them, the module system offers alternatives:
  • Instead of using compact profiles, create run-time images with jlink and configure compilation with --limit-modules.
  • Instead of the extension mechanism or the endorsed standards mechanism, use --patch-module, --upgrade-module-path, or the class path.
  • Instead of the -Xbootclasspath option, use --system, --release, or --patch-module.
  • It’s no longer possible to compile for Java 5 or to use the -version:N option to launch an application with Java version N.
  • Java’s command-line tools and the system property java.version report their version as 9.${MINOR}.${SECURITY}.${PATCH} (in Java 9) or as ${FEATURE}.${INTERIM}.${UPDATE}.${PATCH} (in Java 10 and later), meaning on Java X they start with X instead of 1.x. A new API Runtime.Version makes parsing that property unnecessary.
  • The following tools were removed:
  • In Java 9: JavaDB, VisualVM, hprof, jhat, java-rmi.exe, java-rmi.cgi, and native2ascii
  • In Java 10: policytool
  • In Java 11: idlj, orbd, schemagen, servertool, tnameserv, wsgen, wsimport, and xjc
  • The single underscore is no longer a valid identifier.
  • The JNLP syntax has been updated to conform with the XML specification, so you may have to update your JNLP files.
  • Each Java version removes deprecated JVM command-line options, which may break some of your scripts.
  • Java 9 deprecates the Applet technology and Java Web Start, and Java 11 removes them.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.227.10.45