Skip to content

Commit

Permalink
issue #166: configure dynamic AppCDS when customImage is used
Browse files Browse the repository at this point in the history
  • Loading branch information
siordache committed Dec 21, 2020
1 parent 1ba19ce commit 1c3fe65
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 22 deletions.
53 changes: 44 additions & 9 deletions doc/user_guide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -189,22 +189,54 @@ jlink {
----
|===

[maroon]##enableCds##():: [red]##Experimental## +
[#cds]
[maroon]##enableCds##(Action<CdsData> [purple]##action## = null):: [red]##Experimental - requires Java 13 or newer## +
Enables Class Data Sharing (CDS). +
[purple]##**action**##: an optional script block for configuring the class data sharing. +
&nbsp;&nbsp;&nbsp;&nbsp; _Parameters:_ +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [purple]##**sharedArchiveFile**##: the path and name of the class data sharing archive file. +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; It supports the Mustache syntax and placeholders described in the <<launcher>> section. +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _defaultValue:_ +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; `lib/server/<appName>.jsa` on Unix-like systems +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; `bin\server\<appName>.jsa` on Windows



[cols="1,100", frame=none, grid=none]
|===
a| a| .Usage example
[source,groovy]
----
jlink {
runtime {
...
enableCds()
}
----

&nbsp;&nbsp;&nbsp;&nbsp; or

[source,groovy]
----
runtime {
...
enableCds {
sharedArchiveFile = "{{HOME_DIR}}/myApp.jsa"
}
}
----

When the `enableCds` method is used, the plugin creates a base CDS archive of the image by executing
`$imageDir/bin/java -Xshare:dump`. This means that you cannot use `enableCds` when targeting another platform.

When the `customImage` method is used, some modules are not included in the custom runtime image.
In this case, to allow class data sharing for the excluded modules, the plugin also configures a dynamic AppCDS archive in the start scripts.
If no file is found at the `sharedArchiveFile` location, the application is started with the `-XX:ArchiveClassesAtExit` option,
which will create a dynamic AppCDS archive at this location.
Otherwise, the application is started with the `-XX:SharedArchiveFile` option and uses the existing AppCDS archive.

[purple]##_NOTE_##: Start scripts are not included in the installable packages generated by `jpackage`.
As a result, only the base CDS archive of the image is used by the packaged application.

|===


Expand Down Expand Up @@ -296,10 +328,19 @@ jlink {
}
----

[#launcher]
=== launcher

The plugin generates script files for launching your application.
You can customize these scripts by configuring the following properties in the `launcher` block.
These script files can be customized by configuring the `launcher` block.

Environment variables can be included by using the https://en.wikipedia.org/wiki/Mustache_(template_system)[Mustache syntax],
that is, by enclosing their name between `{{` and `}}`.
Additionally, you can use the following placeholders:

- `{{BIN_DIR}}` - the _bin_ directory of the custom runtime image
- `{{HOME_DIR}}` - user's home directory (`$HOME` on Unix-like systems, `%USERPROFILE%` on Windows)


name:: The base name of the script files used to launch your application. +
_defaultValue_: `project.name`
Expand Down Expand Up @@ -328,12 +369,6 @@ to parse the templates, with the following variables available:
- jvmArgs
- args

The values in the *args* and *jvmArgs* lists may contain the following placeholders:

- `{{BIN_DIR}}` - the _bin_ directory of the custom runtime image
- `{{HOME_DIR}}` - user's home directory (`$HOME` on Unix-like systems, `%USERPROFILE%` on Windows)

You can include the value of an environment variable in a JVM argument by enclosing the name of the environment variable between `{{` and `}}`.

_Usage example_
[source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
Expand Down
6 changes: 3 additions & 3 deletions src/main/groovy/org/beryx/jlink/JlinkTask.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ class JlinkTask extends BaseTask {
}

@Input
boolean isCdsEnabled() {
extension.cdsEnabled.get()
CdsData getCdsData() {
extension.cdsData.get()
}

JlinkTask() {
Expand All @@ -119,7 +119,7 @@ class JlinkTask extends BaseTask {
taskData.javaHome = javaHome
taskData.targetPlatforms = targetPlatforms
taskData.jlinkJarsDir = jlinkJarsDir.asFile
taskData.cdsEnabled = cdsEnabled
taskData.cdsData = cdsData

def taskImpl = new JlinkTaskImpl(project, taskData)
taskImpl.execute()
Expand Down
29 changes: 29 additions & 0 deletions src/main/groovy/org/beryx/jlink/data/CdsData.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.beryx.jlink.data

import groovy.transform.CompileStatic
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional

@CompileStatic
class CdsData implements Serializable {
@Input
boolean enabled

@Input @Optional
String sharedArchiveFile
}
13 changes: 8 additions & 5 deletions src/main/groovy/org/beryx/jlink/data/JlinkPluginExtension.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class JlinkPluginExtension {
final Property<String> moduleName
final Property<String> mergedModuleName
final Property<String> mergedModuleJarName
final Property<Boolean> cdsEnabled
final Property<CdsData> cdsData

/** @deprecated - use {@link ModuleInfo#version} instead */
@Deprecated(since = "2.22.1", forRemoval = true)
Expand Down Expand Up @@ -134,8 +134,8 @@ class JlinkPluginExtension {
def jpd = new JPackageData(project, ld)
jpackageData.set(jpd)

cdsEnabled = project.objects.property(Boolean)
cdsEnabled.set(false)
cdsData = project.objects.property(CdsData)
cdsData.set(new CdsData())
}

void addExtraDependencies(String... dependencies) {
Expand Down Expand Up @@ -193,8 +193,11 @@ class JlinkPluginExtension {
action.execute(jpackageData.get())
}

void enableCds() {
cdsEnabled.set(true)
void enableCds(Action<CdsData> action = null) {
cdsData.get().enabled = true
if(action) {
action.execute(cdsData.get())
}
}

private static String getDefaultJavaHome() {
Expand Down
2 changes: 1 addition & 1 deletion src/main/groovy/org/beryx/jlink/data/JlinkTaskData.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,5 @@ class JlinkTaskData extends BaseTaskData {
File jlinkJarsDir
List<String> extraModulePaths
CustomImageData customImageData
boolean cdsEnabled
CdsData cdsData
}
6 changes: 5 additions & 1 deletion src/main/groovy/org/beryx/jlink/impl/JlinkTaskImpl.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ class JlinkTaskImpl extends BaseTaskImpl<JlinkTaskData> {
}

void execute() {
if(td.cdsData.enabled && td.customImageData.enabled) {
System.properties['BADASS_CDS_ARCHIVE_FILE_LINUX'] = td.cdsData.sharedArchiveFile ?: '$DIR/../lib/server/$APP_NAME.jsa'
System.properties['BADASS_CDS_ARCHIVE_FILE_WINDOWS'] = td.cdsData.sharedArchiveFile ?: '%~dp0\\server\\%~n0.jsa'
}
if(td.targetPlatforms) {
td.targetPlatforms.values().each { platform ->
File imageDir = new File(td.imageDir, "$td.launcherData.name-$platform.name")
Expand All @@ -61,7 +65,7 @@ class JlinkTaskImpl extends BaseTaskImpl<JlinkTaskData> {

@CompileDynamic
void createCDSArchive(File imageDir) {
if(td.cdsEnabled) {
if(td.cdsData.enabled) {
project.exec {
commandLine = ["$imageDir/bin/java", "-Xshare:dump"]
}
Expand Down
14 changes: 13 additions & 1 deletion src/main/resources/unixScriptTemplate.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
#!/bin/sh
SCRIPT_NAME=\$(basename "\$0")
APP_NAME=\${SCRIPT_NAME%.sh}

DIR="\${0%/*}"
"\$DIR/java" ${jvmArgs} -p "\$DIR/../app" -m ${moduleName}/${mainClassName} ${args} "\$@"

<% if ( System.properties['BADASS_CDS_ARCHIVE_FILE_LINUX'] ) { %>
CDS_ARCHIVE_FILE="<%= System.properties['BADASS_CDS_ARCHIVE_FILE_LINUX'] %>"
CDS_JVM_OPTS="-XX:ArchiveClassesAtExit=\$CDS_ARCHIVE_FILE"
if [ -f "\$CDS_ARCHIVE_FILE" ]; then
CDS_JVM_OPTS="-XX:SharedArchiveFile=\$CDS_ARCHIVE_FILE"
fi
<% } %>

"\$DIR/java" \$CDS_JVM_OPTS ${jvmArgs} -p "\$DIR/../app" -m ${moduleName}/${mainClassName} ${args} "\$@"
9 changes: 8 additions & 1 deletion src/main/resources/windowsScriptTemplate.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
@echo off
set DIR="%~dp0"
set JAVA_EXEC="%DIR:"=%\\java"
pushd %DIR% & %JAVA_EXEC% ${jvmArgs} -p "%~dp0/../app" -m ${moduleName}/${mainClassName} ${args} %* & popd

<% if ( System.properties['BADASS_CDS_ARCHIVE_FILE_WINDOWS'] ) { %>
set CDS_ARCHIVE_FILE="<%= System.properties['BADASS_CDS_ARCHIVE_FILE_WINDOWS'] %>"
set CDS_JVM_OPTS=-XX:ArchiveClassesAtExit=%CDS_ARCHIVE_FILE%
if exist %CDS_ARCHIVE_FILE% set CDS_JVM_OPTS=-XX:SharedArchiveFile=%CDS_ARCHIVE_FILE%
<% } %>

pushd %DIR% & %JAVA_EXEC% %CDS_JVM_OPTS% ${jvmArgs} -p "%~dp0/../app" -m ${moduleName}/${mainClassName} ${args} %* & popd
9 changes: 8 additions & 1 deletion src/main/resources/windowsScriptTemplateJavaw.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
@echo off
set DIR="%~dp0"
set JAVA_EXEC="%DIR:"=%\\javaw"
pushd %DIR% & start "${moduleName}" %JAVA_EXEC% ${jvmArgs} -p "%~dp0/../app" -m ${moduleName}/${mainClassName} ${args} %* & popd

<% if ( System.properties['BADASS_CDS_ARCHIVE_FILE_WINDOWS'] ) { %>
set CDS_ARCHIVE_FILE="<%= System.properties['BADASS_CDS_ARCHIVE_FILE_WINDOWS'] %>"
set CDS_JVM_OPTS=-XX:ArchiveClassesAtExit=%CDS_ARCHIVE_FILE%
if exist %CDS_ARCHIVE_FILE% set CDS_JVM_OPTS=-XX:SharedArchiveFile=%CDS_ARCHIVE_FILE%
<% } %>

pushd %DIR% & start "${moduleName}" %JAVA_EXEC% %CDS_JVM_OPTS% ${jvmArgs} -p "%~dp0/../app" -m ${moduleName}/${mainClassName} ${args} %* & popd

0 comments on commit 1c3fe65

Please sign in to comment.