Added configuration options to set the minimum/maximum JVM heap size as percentage of the total physical memory.

This commit is contained in:
LoRd_MuldeR 2023-03-26 18:11:00 +02:00
parent 735a0839ee
commit 656d4145c1
5 changed files with 91 additions and 24 deletions

View File

@ -1,4 +1,4 @@
Copyright 2020 LoRd_MuldeR <mulder2@gmx.de> Copyright 2023 LoRd_MuldeR <mulder2@gmx.de>
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in

View File

@ -74,7 +74,7 @@ Launch5j executables come in a number of variants, allowing you to pick the most
At this time, the following Java distributions can be detected from the registry: At this time, the following Java distributions can be detected from the registry:
- [Oracle JDK (JavaSoft)](https://www.oracle.com/java/technologies/javase-downloads.html) - [Oracle JDK (JavaSoft)](https://www.oracle.com/java/technologies/javase-downloads.html)
- [AdoptOpenJDK](https://adoptopenjdk.net/) - [Eclipse Adoptium](https://adoptium.net/)
- [Liberica OpenJDK](https://bell-sw.com/) - [Liberica OpenJDK](https://bell-sw.com/)
- [Zulu OpenJDK](https://www.azul.com/downloads/zulu-community/) - [Zulu OpenJDK](https://www.azul.com/downloads/zulu-community/)
@ -109,24 +109,24 @@ It is ***not*** necessary to re-build the executable files for that purpose. Ins
Some options can be configured via the launcher executable's [STRINGTABLE](https://docs.microsoft.com/en-us/windows/win32/menurc/stringtable-resource) resource: Some options can be configured via the launcher executable's [STRINGTABLE](https://docs.microsoft.com/en-us/windows/win32/menurc/stringtable-resource) resource:
* **`ID_STR_HEADING` (#1)** * **`ID_STR_HEADING` (0x1)**
Specifies a custom application title that will be used, e.g., as the heading of message boxes. Specifies a custom application title that will be used, e.g., as the heading of message boxes.
* **`ID_STR_JVMARGS` (#2)** * **`ID_STR_JVMARGS` (0x2)**
Specifies *additional* options JVM options to be passed, such as `-Xmx2g` or `-Dproperty=value`. Specifies *additional* options JVM options to be passed, such as `-Xmx2g` or `-Dproperty=value`.
See here for a list of available options: See here for a list of available options:
<https://docs.oracle.com/javase/7/docs/technotes/tools/windows/java.html> <https://docs.oracle.com/javase/7/docs/technotes/tools/windows/java.html>
* **`ID_STR_CMDARGS` (#3)** * **`ID_STR_CMDARGS` (0x3)**
Specifies *additional* fixed command-line parameters to be passed to the Java application. Specifies *additional* fixed command-line parameters to be passed to the Java application.
* **`ID_STR_JREPATH` (#4)** * **`ID_STR_JREPATH` (0x4)**
Specifies the path to the Java runtime (`javaw.exe`) relative to the launcher executable location. Specifies the path to the Java runtime (`javaw.exe`) relative to the launcher executable location.
If not specified, then the *default* runtime path `runtime\\bin\\javaw.exe` is assumed. If not specified, then the *default* runtime path `runtime\\bin\\javaw.exe` is assumed.
(This option does **not** apply to the “registry” variant of Launch5j) (This option does **not** apply to the “registry” variant of Launch5j)
* **`ID_STR_MUTEXID` (#5)** * **`ID_STR_MUTEXID` (0x5)**
Specifies the application ID to be used when creating the [*single-instance*](http://www.bcbjournal.org/articles/vol3/9911/Single-instance_applications.htm) mutex. Specifies the application ID to be used when creating the [*single-instance*](http://www.bcbjournal.org/articles/vol3/9911/Single-instance_applications.htm) mutex.
The ID **must** be at least 5 characters in length and **should** be a *unique* string for each application! The ID **must** be at least 5 characters in length and **should** be a *unique* string for each application!
If not specified, then **no** mutex will be created and thus *multiple* instances will be allowed. If not specified, then **no** mutex will be created and thus *multiple* instances will be allowed.
@ -135,7 +135,19 @@ Some options can be configured via the launcher executable's [STRINGTABLE](https
(This option does **not** apply to the “nowait” variant of Launch5j) (This option does **not** apply to the “nowait” variant of Launch5j)
* **`ID_STR_JAVAMIN` (#6)** * **`ID_STR_HEAPMIN` (0x6)**
Specifies the the ***minimum*** Java heap size (i.e. JVM option `-Xms`), as percentage of the total physical memory.
This must be an integral value in the `1` to `100` range, and it must be less than or equal to `ID_STR_HEAPMAX`.
(This option **must** be specified together with `ID_STR_HEAPMAX`)
* **`ID_STR_HEAPMAX` (0x7)**
Specifies the the ***maximum*** Java heap size (i.e. JVM option `-Xmx`), as percentage of the total physical memory.
This must be an integral value in the `1` to `100` range, and it must be greater than or equal to `ID_STR_HEAPMIN`.
(This option **must** be specified together with `ID_STR_HEAPMIN`)
* **`ID_STR_JAVAMIN` (0x8)**
Specifies the ***minimum*** supported JRE version, in the **`w.x.y.z`** format (e.g. `11.0.0.0`). Specifies the ***minimum*** supported JRE version, in the **`w.x.y.z`** format (e.g. `11.0.0.0`).
This values is *inclusive*, i.e. the specified JRE version or any newer JRE version will be accepted. This values is *inclusive*, i.e. the specified JRE version or any newer JRE version will be accepted.
If not specified, then the *default* minimum supported JRE version `8.0.0.0` applies. If not specified, then the *default* minimum supported JRE version `8.0.0.0` applies.
@ -144,7 +156,7 @@ Some options can be configured via the launcher executable's [STRINGTABLE](https
(This option only applies to the “registry” variant of Launch5j) (This option only applies to the “registry” variant of Launch5j)
* **`ID_STR_JAVAMAX` (#7)** * **`ID_STR_JAVAMAX` (0x9)**
Specifies the ***maximum*** supported JRE version, in the **`w.x.y.z`** format (e.g. `12.0.0.0`). Specifies the ***maximum*** supported JRE version, in the **`w.x.y.z`** format (e.g. `12.0.0.0`).
This values is *exclusive*, i.e. only JRE versions *older* than the specified JRE version will be accepted. This values is *exclusive*, i.e. only JRE versions *older* than the specified JRE version will be accepted.
If not specified, then there is **no** upper limit on the supported JRE version. If not specified, then there is **no** upper limit on the supported JRE version.
@ -153,15 +165,15 @@ Some options can be configured via the launcher executable's [STRINGTABLE](https
(This option only applies to the “registry” variant of Launch5j) (This option only applies to the “registry” variant of Launch5j)
* **`ID_STR_BITNESS` (#8)** * **`ID_STR_BITNESS` (0xA)**
Specifies the required ***bitness*** of the JRE. This can be either **`32`** (x86, aka i586) or **`64`** (x86-64). Specifies the required ***bitness*** of the JRE. This can be either **`32`** (x86, aka i586) or **`64`** (x86-64).
If not specified, then 32-Bit *and* 64-Bit JREs are accepted, with a preference to 64-Bit. If not specified, then 32-Bit *and* 64-Bit JREs are accepted, with a preference to 64-Bit.
(This option only applies to the “registry” variant of Launch5j) (This option only applies to the “registry” variant of Launch5j)
* **`ID_STR_JAVAURL` (#9)** * **`ID_STR_JAVAURL` (0xB)**
The Java download URL that will ne suggested, if **no** suitable JRE could be detected on the machine. The Java download URL that will ne suggested, if **no** suitable JRE could be detected on the machine.
If not specified, wes suggest downloading OpenJDK as provided by the [AdoptOpenJDK](https://adoptopenjdk.net/) project. If not specified, wes suggest downloading OpenJDK, as provided by the [Eclipse Adoptium](https://adoptium.net/) project.
*Hint:* The URL must begin with a `http://` or `https://` prefix; otherwise the URL will be ignored! *Hint:* The URL must begin with a `http://` or `https://` prefix; otherwise the URL will be ignored!
@ -284,7 +296,7 @@ This project is partly inspired by the “Launch4j” project, even though it ha
This work has been released under the MIT license: This work has been released under the MIT license:
Copyright 2020 LoRd_MuldeR <mulder2@gmx.de> Copyright 2023 LoRd_MuldeR <mulder2@gmx.de>
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in

View File

@ -42,6 +42,8 @@ BEGIN
ID_STR_CMDARGS L"?" /*additional command-line args*/ ID_STR_CMDARGS L"?" /*additional command-line args*/
ID_STR_JREPATH L"?" /*relative path to JRE*/ ID_STR_JREPATH L"?" /*relative path to JRE*/
ID_STR_MUTEXID L"?" /*single instance mutex ID*/ ID_STR_MUTEXID L"?" /*single instance mutex ID*/
ID_STR_HEAPMIN L"?" /*min. heap size, in percent of phys. memory*/
ID_STR_HEAPMAX L"?" /*max. heap size, in percent of phys. memory*/
END END
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////

View File

@ -65,6 +65,7 @@ static const wchar_t *const JRE_DOWNLOAD_LINK_DEFAULT = L"https://adoptium.net/"
static const wchar_t *const JRE_RELATIVE_PATH_DEFAULT = L"runtime\\bin"; static const wchar_t *const JRE_RELATIVE_PATH_DEFAULT = L"runtime\\bin";
static const wchar_t *const JRE_EXECUTABLE_NAME = L5J_ENABLE_GUI ? L"javaw.exe" : L"java.exe"; static const wchar_t *const JRE_EXECUTABLE_NAME = L5J_ENABLE_GUI ? L"javaw.exe" : L"java.exe";
static const size_t MIN_MUTEXID_LENGTH = 5U; static const size_t MIN_MUTEXID_LENGTH = 5U;
static const size_t BYTES_PER_MEGABYTE = 1024U * 1024U;
static const DWORD SPLASH_SCREEN_TIMEOUT = 30000U; static const DWORD SPLASH_SCREEN_TIMEOUT = 30000U;
// Check platform // Check platform
@ -323,6 +324,18 @@ static BOOL running_on_64bit(void)
#endif #endif
} }
static ULONGLONG get_physical_memory_size()
{
MEMORYSTATUSEX memory_status;
ZeroMemory(&memory_status, sizeof(MEMORYSTATUSEX));
memory_status.dwLength = sizeof(MEMORYSTATUSEX);
if (GlobalMemoryStatusEx(&memory_status))
{
return memory_status.ullTotalPhys;
}
return 0L;
}
/* ======================================================================== */ /* ======================================================================== */
/* File name routines */ /* File name routines */
/* ======================================================================== */ /* ======================================================================== */
@ -521,7 +534,7 @@ static DWORD load_uint32(const HINSTANCE hinstance, const UINT id, const DWORD f
{ {
DWORD value = fallback; DWORD value = fallback;
const wchar_t *const str = load_string(hinstance, id); const wchar_t *const str = load_string(hinstance, id);
if(NOT_EMPTY(str)) if(AVAILABLE(str))
{ {
value = wcstoul(str, NULL, 10); value = wcstoul(str, NULL, 10);
} }
@ -1201,6 +1214,26 @@ static const wchar_t *encode_commandline_str(const wchar_t *const command_line)
return encoded; return encoded;
} }
const wchar_t *create_heap_size_parameters(const DWORD jvm_heap_percent_min, const DWORD jvm_heap_percent_max, const wchar_t *const jvm_extra_args)
{
if ((jvm_heap_percent_min > 0U) && (jvm_heap_percent_max >= jvm_heap_percent_min))
{
const ULONGLONG physical_memory_size = get_physical_memory_size();
if (physical_memory_size > 0ULL)
{
const DWORD heap_size_mbytes_min = (DWORD)((((ULONGLONG)((jvm_heap_percent_min / (double)100U) * physical_memory_size)) + (BYTES_PER_MEGABYTE - 1U)) / BYTES_PER_MEGABYTE);
const DWORD heap_size_mbytes_max = (DWORD)((((ULONGLONG)((jvm_heap_percent_max / (double)100U) * physical_memory_size)) + (BYTES_PER_MEGABYTE - 1U)) / BYTES_PER_MEGABYTE);
if ((heap_size_mbytes_min > 0U) && (heap_size_mbytes_max >= heap_size_mbytes_min))
{
return AVAILABLE(jvm_extra_args)
? aswprintf(L"-Xms%um -Xmx%um %s", heap_size_mbytes_min, heap_size_mbytes_max, jvm_extra_args)
: aswprintf(L"-Xms%um -Xmx%um", heap_size_mbytes_min, heap_size_mbytes_max);
}
}
}
return NULL;
}
static const wchar_t *build_commandline(const DWORD pid, const wchar_t *const java_runtime_path, const wchar_t *const jar_file_path, const wchar_t *const jvm_extra_args, const wchar_t *const cmd_extra_args, const wchar_t *const cmd_input_args) static const wchar_t *build_commandline(const DWORD pid, const wchar_t *const java_runtime_path, const wchar_t *const jar_file_path, const wchar_t *const jvm_extra_args, const wchar_t *const cmd_extra_args, const wchar_t *const cmd_input_args)
{ {
const wchar_t *command_line; const wchar_t *command_line;
@ -1549,6 +1582,11 @@ static void destroy_window(HWND *const hwnd)
} }
} }
static DWORD bound_value(const DWORD min_value, const DWORD value, const DWORD max_value)
{
return max(min_value, min(max_value, value));
}
/* ======================================================================== */ /* ======================================================================== */
/* MAIN */ /* MAIN */
/* ======================================================================== */ /* ======================================================================== */
@ -1562,7 +1600,7 @@ static int launch5j_main(const HINSTANCE hinstance, const wchar_t *const cmd_lin
const wchar_t *app_heading = NULL, *mutex_name = NULL, *executable_path = NULL, *executable_directory = NULL, *jarfile_path = NULL, const wchar_t *app_heading = NULL, *mutex_name = NULL, *executable_path = NULL, *executable_directory = NULL, *jarfile_path = NULL,
*java_runtime_path = NULL, *jre_relative_path = NULL, *jvm_extra_args = NULL, *cmd_extra_args = NULL, *command_line = NULL; *java_runtime_path = NULL, *jre_relative_path = NULL, *jvm_extra_args = NULL, *cmd_extra_args = NULL, *command_line = NULL;
HANDLE mutex_handle = NULL; HANDLE mutex_handle = NULL;
DWORD java_required_bitness = 0U; DWORD java_required_bitness = 0U, jvm_heap_percent_min = 0U, jvm_heap_percent_max = 0U;
ULONGLONG java_required_ver_min = 0ULL, java_required_ver_max = 0ULL; ULONGLONG java_required_ver_min = 0ULL, java_required_ver_max = 0ULL;
HGDIOBJ splash_image = NULL; HGDIOBJ splash_image = NULL;
BOOL have_screen_created = FALSE; BOOL have_screen_created = FALSE;
@ -1693,6 +1731,19 @@ static int launch5j_main(const HINSTANCE hinstance, const wchar_t *const cmd_lin
jvm_extra_args = load_string(hinstance, ID_STR_JVMARGS); jvm_extra_args = load_string(hinstance, ID_STR_JVMARGS);
cmd_extra_args = load_string(hinstance, ID_STR_CMDARGS); cmd_extra_args = load_string(hinstance, ID_STR_CMDARGS);
// Set minimum/maximum Java heap size
jvm_heap_percent_min = bound_value(0U, load_uint32(hinstance, ID_STR_HEAPMIN, 0U), 100U);
jvm_heap_percent_max = bound_value(0U, load_uint32(hinstance, ID_STR_HEAPMAX, 0U), 100U);
if ((jvm_heap_percent_min != 0U) && (jvm_heap_percent_max != 0U))
{
const wchar_t *const jvm_heap_size_args = create_heap_size_parameters(jvm_heap_percent_min, jvm_heap_percent_max, jvm_extra_args);
if (jvm_heap_size_args)
{
free((void*)jvm_extra_args);
jvm_extra_args = jvm_heap_size_args;
}
}
// Make sure command-line was created // Make sure command-line was created
command_line = build_commandline(pid, java_runtime_path, jarfile_path, jvm_extra_args, cmd_extra_args, cmd_line_args); command_line = build_commandline(pid, java_runtime_path, jarfile_path, jvm_extra_args, cmd_extra_args, cmd_line_args);
if (!command_line) if (!command_line)

View File

@ -31,14 +31,16 @@
#define ID_BITMAP_SPLASH 1 #define ID_BITMAP_SPLASH 1
// STRINGS // STRINGS
#define ID_STR_HEADING 1 #define ID_STR_HEADING 0x1
#define ID_STR_JVMARGS 2 #define ID_STR_JVMARGS 0x2
#define ID_STR_CMDARGS 3 #define ID_STR_CMDARGS 0x3
#define ID_STR_JREPATH 4 #define ID_STR_JREPATH 0x4
#define ID_STR_MUTEXID 5 #define ID_STR_MUTEXID 0x5
#define ID_STR_JAVAMIN 6 #define ID_STR_HEAPMIN 0x6
#define ID_STR_JAVAMAX 7 #define ID_STR_HEAPMAX 0x7
#define ID_STR_BITNESS 8 #define ID_STR_JAVAMIN 0x8
#define ID_STR_JAVAURL 9 #define ID_STR_JAVAMAX 0x9
#define ID_STR_BITNESS 0xA
#define ID_STR_JAVAURL 0xB
#endif #endif