Skip to content

JEP 411

Chapman Flack edited this page Mar 23, 2025 · 9 revisions

PL/Java and JEP 411: Java 17, Java 24, and beyond

Changes in Java, first announced with Java 17 and of serious consequence in Java 24, force important functional changes in PL/Java.

Permissions and enforcement in PL/Java

PL/Java supports at least two PostgreSQL CREATE LANGUAGE declarations, one with and one without the TRUSTED property, and enforces limits on what a function declared in the TRUSTED language can do. The PL/Java 1.6 series goes further and makes those restrictions configurable, and more than two PL/Java "languages" can be declared, with different configurable restrictions for each, as described in the documentation.

To provide and support these controls, PL/Java relies on many features of the groundbreaking Java 2 security architecture as specified in 2002.

Changes in Java 17 and beyond: JEP 411

In April 2021, the Java developers announced a JDK Enhancement Proposal, JEP 411, to remove this functionality from Java over a series of releases, with the first changes already shipped in Java 17.

As originally described, the "major components of the security model are security policy, access permissions, protection domain, access control checking, privileged operation, and class loading and resolution." JEP 411 announced eventual elimination of the first, fourth and fifth, with the second and third to remain in vestigial form. PL/Java's policy enforcement relies on the affected Java features.

Java 17

In Java 17, all of the functionality remains; only warnings and deprecation markings have been added. Java 17 and 21 are also positioned as long-term support releases, successors in that role to Java 11. It will therefore be possible to run current PL/Java versions without difficulty for a number of years.

However, Java 17 will be designed to write an unconditional warning on its standard error channel (which will go into PostgreSQL's log file, if logging_collector is enabled), every time any backend loads PL/Java. The JEP 411 proponents rebuffed requests to allow a higher layer, like PL/Java, to suppress the low-level JVM warning and issue one that is layer-appropriate (such as an explanation about trusted functions or a link to this wiki page).

The JVM's boilerplate warning will look like this:

WARNING: A terminally deprecated method in java.lang.System has been called
WARNING: System::setSecurityManager has been called by org.postgresql.pljava.internal.Backend
WARNING: Please consider reporting this to the maintainers of org.postgresql.pljava.internal.Backend
WARNING: System::setSecurityManager will be removed in a future release

As much as the warnings will urge you, please do not consider reporting them to the maintainers of PL/Java.

The PL/Java 1.6 series, as described below, does attempt to suppress the boilerplate JVM warning, and issue a "migration advisory" ereport of a more useful nature, only upon certain administrative actions like CREATE EXTENSION or installing a jar, and no more than once in a session. That should cut down on the log spam.

Java 18 through 23

When run on Java 18 through 23, PL/Java can still provide policy enforcement and a trusted/untrusted language distinction, but requires a specific JVM option added in the pljava.vmoptions configuration setting:

  • -Djava.security.manager=allow will allow PL/Java to work as it always has, with policy enforcement
  • -Djava.security.manager=disallow will allow running PL/Java (1.6.9 or later) with no policy enforcement, as described in new documentation

Without one or the other of those settings, PL/Java 1.5 or 1.6 will fail to start on Java 18 through 23.

Java 24 and later

With Java 24, only the -Djava.security.manager=disallow option (and therefore only PL/Java 1.6.9 or later) will work, as the crucial Java language features are no longer implemented. Where policy enforcement is needed, current PL/Java releases should be run on any earlier Java version, including 17 and 21, which are positioned for long-term support.

In some future Java version, the needed Java features will not be merely unimplemented but removed from the API, and current PL/Java versions will fail to compile, and fail with linkage errors at runtime. A future PL/Java version will be needed that eliminates hard dependencies on the affected APIs.

Plans for PL/Java release series

PL/Java 1.5 series

PL/Java 1.5 is the series minimally maintained for legacy support (PostgreSQL back to 8.2, Java back to 6). Its build process requires Java 14 or earlier, but it can be run on later Java versions. Minimal changes will be made in 1.5.

  • Because it already does not support building on newer Java versions, it will not need any source code changes to suppress the new deprecation warnings.
  • It will make no attempt to intercept the fixed warning message described above. When running on Java 17 or later, that warning will be written on the backend's standard error channel, every time a backend starts PL/Java.
  • Code will not be added to automatically supply the -Djava.security.manager=allow option for any Java version.
  • Code will be added (in 1.5.8) to attempt to detect when the needed components have become no-ops, and then throw an exception rather than executing any function declared as trusted.

Options if that exception is seen can include:

  • Continuing to use PL/Java 1.5, downgrading Java to the preceding version
  • Changing all trusted function declarations to untrusted and accepting that they will run without security enforcement
  • Upgrading to a newer PL/Java version if available.

Note that even functions declared as untrusted have normally had a few limits enforced in PL/Java 1.5, and even those limits will be unenforced if running on a version of Java where the needed components are no-ops.

PL/Java 1.6 series

PL/Java 1.6 is the current recommended series covering PostgreSQL 9.5 and later, Java 9 and later.

  • Code added in 1.6.3 attempts to suppress the boilerplate, low-level warning from the JVM, so that more meaningful notice in relevant PL/Java terms can be given. Suppression of the boilerplate is best-effort, relying on JDK internals, given the rebuffed request for an exposed control serving that purpose.
  • Code added in 1.6.3:
    • Issues warnings (or notices) of the upcoming JEP 411 impacts, including a link to this wiki page
    • Issues the warning whenever the runtime Java major version is above 11, so as to warn not only sites that have moved from 11 LTS to 17 LTS, but also sites that update more frequently between LTS versions
    • Issues the warning when PL/Java is installed or upgraded, or when a cluster that has PL/Java installed undergoes a binary pg_upgrade (in the pg_upgrade case, the warning will be unconditional, because no JVM is started at that time to query its version)
    • Issues the warning, at most one per session, at commit of a transaction that has declared or redeclared at least one PL/Java function
    • Refuses to execute, if the needed support is detectably stubbed out, unless a special configuration option is set
  • Code added in 1.6.9:
  • 1.6.9 will not be usable on whatever version of Java finally removes the deprecated APIs. It will fail with linkage errors.
  • A release after 1.6.9 may also be adapted to run without linkage errors on a Java version where the APIs have been finally removed.

Note that even functions declared as untrusted run with significant limits by default in PL/Java 1.6, and the limits on both trusted and untrusted functions are configurable in policy, and all such limits will be unenforced if running without enforcement. The new documentation should be reviewed carefully before using PL/Java in that mode.

PL/Java 1.6 will continue to see active development for the foreseeable future. The existing enforcement mechanisms remain functional through Java 23, including Java 21 LTS, and for some applications, its fine-grained security policy may remain more attractive than what post-JEP-411 versions will support.

PL/Java ?.?

A new major version of PL/Java will need to be developed that can support some notion of trusted-function enforcement without relying on the rescinded Java mechanisms.

This will be a big undertaking, and will have to scale back expectations to a much more basic model of what can be enforced: chiefly filesystem access, process manipulations, and IPC. The result will probably land somewhere more fine-grained and configurable than PL/Java 1.5, but much less so than 1.6.

All usual disclaimers about forward-looking statements must be applied.

During that development, both existing PL/Java series can continue to be used with the limitations described above.

An OpenJDK fork to maintain policy enforcement

A fork of OpenJDK, independent of the PL/Java project, has been made whose goal is to track the feature development of OpenJDK 24 and later while maintaining support for policy enforcement.

If the project is successful and proves usable as a JVM runtime for PL/Java, it may offer an attractive option for applications where both policy enforcement and the most modern Java language features are wanted. It may be worthy of support by organizations seeking such an option.

That project can be found on GitHub here.

This page will be updated as more is learned about that project's success and usability with PL/Java.

Clone this wiki locally