Class Loaders
This section strictly applies to Payara Server. |
Payara Server extends the default JVM classloading and provides additional classes, which are loaded by the class loaders included by default on this distribution. Understanding Payara Server class loaders can help you determine where to place supporting JAR and resource files for your modules and applications.
Understanding Payara Server class loaders can help you determine where to place supporting JAR and resource files for your modules and applications.
In a JVM implementation, the class loaders dynamically load a specific Java class file needed for resolving a dependency. For example, when an instance of java.util.Enumeration
needs to be created, one of the class loaders loads the relevant class into the environment.
For information about class loader debugging, see Class Loader Debugging.
Standard Classloading
In a JVM implementation, the class loaders dynamically load a specific Java class file needed for resolving a dependency. For example, when an instance of java.util.Enumeration
needs to be created, one of the class loaders loads the relevant class into the environment.
For information about class loader debugging, see Class Loader Debugging.
Class loaders in Payara Server follow a delegation hierarchy by default.
The Class Loader Hierarchy
Class loaders in the Payara Server runtime follow a delegation hierarchy that is illustrated in the following table:
Class Loader | Description | ||
---|---|---|---|
Bootstrap |
The Bootstrap class loader loads the basic runtime classes provided by the JVM. |
||
Extension |
The Extension class loader loads classes from JAR files present in the system extensions directory,
|
||
Public API |
The Public API class loader makes available all classes specifically exported by the Payara Server runtime for use by deployed applications. This includes, but is not limited to, Jakarta EE API, Eclipse MicroProfile and the Payara Platform Public API. Parents the Common class loader. |
||
Common |
The Common class loader loads JAR files in the`as-install/lib` directory, followed by JAR files in the Using Parents the Connector class loader. |
||
Connector |
The Connector class loader is a single class loader instance that loads individually deployed connector modules, which are shared across all applications. Parents both the Applib class loader and the LifeCycleModule class loader. |
||
LifeCycleModule |
The LifeCycleModule class loader is created once per lifecycle module. Each lifecycle module’s classpath is used to construct its own class loader. For more information on lifecycle modules, see Developing Lifecycle Listeners. |
||
Applib |
The One instance of this class loader is present in each class loader universe; Parents the Archive class loader.
|
||
Archive |
The Archive class loader loads classes from the WAR, EAR, and JAR files or directories (for directory deployment) of applications or modules deployed in Payara Server. This class loader also loads any application-specific classes generated by the Payara Server runtime, such as stub classes or servlets generated by JSP pages. |
Classloaders that are lower in the hierarchy will first delegate searching for a class to a classloader higher in the hierarchy.
If none of the classloaders higher in the hierarchy finds the class, the classloader will attempt to find the class itself. |
Here, you can see that:
-
Classes provided by Payara Server have higher priority than classes provided by an application
-
Classes provided by Payara Server have higher priority than installed libraries of type
common
andapp
. -
Classes in installed libraries have higher priority than classes provided by an application
-
To install a library with a higher priority than classes provided by Payara Server, it should be installed with the
ext
type.
Configuring Delegation
The Jakarta Servlet specification recommends that a web module’s class loader look in the local class loader before delegating to its parent.
You can make this class loader follow the delegation inversion model in the Servlet specification by setting delegate="false"
in the class-loader
element of the payara-web.xml
file. It is safe to do this only for a web module that does not interact with any other modules.
For more details, see "class-loader" in the Payara Server Application Deployment section. An example of how to use this element is given in the disabling classloading delegation on web application section.
The default value is delegate="true"
, which causes a web module’s class loader to delegate in the same manner as the other class loaders. You must use delegate="true"
for a web application that accesses EJB components or that acts as a web service client or endpoint.
For a number of packages, including java.*
and jakarta.\*
, symbol resolution is always delegated to the parent class loader regardless of the delegate
setting. This prevents applications from overriding core Java runtime classes or changing the API versions of specifications that are part of the Jakarta EE platform.
The delegation hierarchy can also be tweaked using the enhanced classloading features. For example, it’s possible to give the classes provided by an application the highest priority (by disabling classloading delegation), or completely hide (isolate) classes provided by Payara Server from a deployed application.
Class Loader Universes
Access to components within applications and modules installed on the server occurs within the context of isolated class loader universes, each of which has its own Applib and Archive classloaders.
- Application Universe
-
Each application has its own class loader universe, which loads the classes in all the modules in the application.
- Individually Deployed Module Universe
-
Each individually deployed EJB JAR or web WAR has its own class loader universe, which loads the classes in the module.
A resource such as a file that is accessed by a Jakarta EE application component must be in one of the following locations:
-
A directory pointed to by the Libraries field or
--libraries
option used during deployment -
A directory pointed to by the
library-directory
element in theapplication.xml
deployment descriptor -
A directory pointed to by the application or module’s classpath; for example, a web module’s classpath includes these directories:
module-name/WEB-INF/classes module-name/WEB-INF/lib
Installing Libraries in a Domain
Since each application or individually deployed module class loader universe is isolated, an application or module cannot load classes from another application or module. This prevents two similarly named classes in different applications or modules from interfering with each other.
To circumvent this limitation for libraries, utility classes, or individually deployed modules accessed by more than one application, you can include the relevant path to the required classes by installing a library with those classes into the server domain. This is useful if you’d like to build an application for flexible deployments and configure it with classes dropped on the classpath, or if you’d like multiple deployed applications to share the same library.
If an internal server resource, such as a JDBC connection pool, requires an additional library, you can install it directly into the Payara Server domain too.
To install a library into a server domain, use the asadmin add-library command.
This command accepts the --type
argument, which accepts the following options:
common
-
The library is installed as a common library into the
lib
directory in the Payara Server domain ext
-
The library is installed as an "extension" library into the
lib/ext
directory in the Payara Server domain app
-
the library is installed as an application library into the
lib/applibs
directory in the Payara Server domain
Common Libraries
Common libraries are available to all applications or modules deployed on servers with the same configuration. There are several levels of common libraries:
-
Shared by all applications deployed on the same Payara Server installation - located in the
glassfish/lib
directory in the Payara Server installation -
Shared by all applications deployed in the same Payara Server domain - located in the
lib
directory in that Payara Server domain directory -
Shared by all applications deployed on instances that share the same configuration - located in the
config/<config-name>/lib
directory in the particular Payara Server domain directory
Only libraries shared by applications in the same domain can be installed by the add-library asadmin command. All other types have to be installed manually by copying the libraries into the particular locations.
|
Extension Libraries
Application developers can use libraries installed as extension libraries to extend the functionality of the core Payara Server platform. For example, an Oracle Database JDBC driver should be installed as an extension library if it’s going to be used via JPA to use Oracle-specific JPA features.
Or a Java agent library should be installed as an extension library if the Java agent instruments classes in Payara Server to use classes from the agent library itself.
Classes in extension libraries will be available to all deployed applications. If you need that classes from an extension library are available also to Payara Server’s internal classes (and OSGi bundles in general) as is often the case with Java agents, you also need to add the packages exported by the library into OSGi boot delegation. |
This is done by modifying the as-install/config/osgi.properties
configuration file in the Payara Server installation and adding the packages to the list in the org.osgi.framework.bootdelegation
property.
Packages exported by Oracle JDBC drivers are already added by default. |
Extension libraries are added to the system classpath at the beginning of the classpath, so that they have higher priority than all other classes and libraries on the classpath. This is because the Java extension mechanism isn’t supported in Java 11 and newer and the official recommend way to replace it is to add the libraries to the classpath directly.
Since defining the java.ext.dirs
on Java 11+ leads to an error, this JVM option cannot be used with Java 11+ and extension libraries are automatically added as classpath elements.
Application Specific Libraries
You can specify module or application-specific library classes in one of the following ways:
-
Use the Administration Console. Open the Applications component, then go to the page for the type of application or module. Select the Deploy button. Type the comma-separated paths in the Libraries field.
-
Use the
asadmin deploy
command with the--libraries
option and specify comma-separated paths. For more details, see the Payara Server Reference Manual. -
Use the
asadmin add-library
command with the--type app
option. For details, see the add-library.
None of these alternatives apply to application clients. For more information, see Using Libraries with Application Clients. |
You can update a library JAR file using dynamic reloading or by restarting (disabling and re-enabling) a module or application. To add or remove library JAR files, you can redeploy the module or application. Application libraries are included in the Applib class loader. Paths to libraries can be relative or absolute.
A relative path is relative to domain-dir/lib/applibs
. If the path is absolute, the path must be accessible to the domain administration server (DAS). Payara Server automatically synchronizes these libraries to all remote instances when a cluster or deployment group is restarted. However, libraries specified by absolute paths are not guaranteed to be synchronized.
You can also use application-specific class loading to access different versions of a library from different applications. |
If multiple applications or modules refer to the same libraries, classes in those libraries are automatically shared. This can reduce the memory footprint and allow sharing of static information. However, applications or modules using application-specific libraries are not portable.
If you see an access control error message when you try to use a library, you may need to grant permission to the library in the
server.policy file. For more information, see Changing Permissions for an Application.
|
Packaging the Client JAR for One Application in Another Application
By packaging the client JAR for one application in a second application, you allow a Jakarta EE component in the second application to call an EJB component in the first (dependent) application, without making either of them accessible to any other application or module.
As an alternative for a production environment, you can have the Common class loader load the client JAR of the dependent application as described in the previous section. |
To do this follow these steps:
-
Deploy the dependent application.
-
Add the dependent application’s client JAR file to the calling application.
-
For a calling EJB component, add the client JAR file at the same level as the EJB component. Then add a
Class-Path
entry to theMANIFEST.MF
file of the calling EJB component. -
For a calling web component, add the client JAR file under the
WEB-INF/lib
directory.If you need to package the client JAR with both the EJB and web components, set
delegate="true"
attribute in theclass-loader
element of thepayara-web.xml
file.This changes the Web class loader so that it follows the standard class loader delegation model and delegates to its parent before attempting to load a class itself.
For most applications, packaging the client JAR file with the calling EJB component is sufficient. You do not need to package the client JAR file with both the EJB and web components unless the web component is directly calling the EJB component in the dependent application.
-
-
Deploy the "client" application. The calling EJB or web component must specify in its
glassfish-ejb-jar.xml
orpayara-web.xml
file the JNDI name of the EJB component in the dependent application. Using anejb-link
mapping does not work when the EJB component being called resides in another application.
Enhanced Classloading
This sections below cover the enhanced class loading functionality provided by the Payara Platform.
Default Class and Library Loading
Payara Server has included many standard Java libraries and packages, for example Jackson, Nimbus JOSE, Logback, and others to use. These libraries are located on the as-install/modules
directory.
The default class loading mechanism of Payara Server works like this: When loading classes that belong to a library or framework that is included in the server, the server will always load those classes even if the application itself includes different versions.
In some cases, application developers will want to include a different version of the libraries that are already included on the server. Common use cases for this are:
-
Use a newer version of a library that is included in the server. For example, Payara Server includes the Jackson library, and you might need to use a newer version that includes a specific feature you want to use.
-
Use an older version of a library included within the server in order to support legacy applications. For example, you are using an older version of Icefaces that depends on an older version of Jakarta Faces.
Unfortunately, due to the way the default class loading hierarchy works, this will not be possible, and all libraries included with the server libraries will take precedence.
Disable Classloading delegation
As detailed in Configuring Delegation, it is possible to invert/disable the way that delegation works as per the requirements of the Jakarta Servlet specification. The Payara Platform introducers greater delegation disabling mechanisms, detailed in the following sections.
Disable Classloading delegation globally
To disable class loading delegation globally, you can set the system property fish.payara.classloading.delegate
to false
.
Disable Classloading delegation locally
It’s possible to disable class loading delegation directly at the application level. This can be done for both WAR and EAR applications.
For Web applications, you can include <class-loader delegate="false"/>
element in the payara-web.xml
/glassfish-web.xml
deployment descriptors.
Here’s an example:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app error-url="">
<class-loader delegate="false"/>
</glassfish-web-app>
For EAR applications, you can include the <classloading-delegate>false</classloading-delegate>
element in the glassfish-application.xml
deployment descriptor.
Here is an example:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-application PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Java EE Application 6.0//EN" "http://glassfish.org/dtds/glassfish-application_6_0-1.dtd">
<glassfish-application>
<classloading-delegate>false</classloading-delegate>
</glassfish-application>
Extreme Classloading Isolation
It’s possible to configure an extreme isolation level on the class loading delegation for deployed applications. With this extreme isolation behavior, a deployed application can force the server to load only classes and resources from libraries included on the server that belong to whitelisted packages defined on its deployment descriptors.
To configure whitelist packaging you can use the <whitelist-package>
element on the payara-web.xml
/ glassfish-web.xml
(for WAR artifacts) or the glassfish-application.xml
(for EAR artifacts) deployment descriptors. This element can be included multiple times to whitelist multiple packages.
Here is an example of whitelisting both the Google Guava, Jackson and Faces Config packages for a WAR application:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app error-url="">
<whitelist-package>com.google.guava</whitelist-package>
<whitelist-package>com.fasterxml.jackson</whitelist-package>
<whitelist-package>com.sun.faces.spi.FacesConfigResourceProvider</whitelist-package>
</glassfish-web-app>
The whitelist syntax is simple: Define the name of the package which contains the classes or resources in question. For example writing com.google
would whitelist all Google libraries included on the server, while writing com.google.guava
would only whitelist the Google Guava library instead.
To enable this extreme isolation behavior, at least one whitelist-package element must be defined in the appropriate descriptor.
|
Default Whitelisted Classes
Certain classes are whitelisted automatically, meaning they will always be loaded from the server libraries and follow the default classloading hierarchy, even if this feature is turned on.
This is because these packages are required by the server and therefore cannot be loaded from application modules:
-
java
-
javax
-
com.sun
-
org.glassfish
-
org.apache.jasper
-
fish.payara
-
com.ibm.jbatch
-
org.hibernate.validator
-
org.jboss.weld
-
com.ctc.wstx
Likewise, the default whitelisted resources are:
-
META-INF/services/jakarta.
-
META-INF/services/org.glassfish.
-
META-INF/services/java.