Skip to content

Commit fac3c2d

Browse files
author
Alexey Semenyuk
committedFeb 5, 2021
8254702: jpackage app launcher crashes on CentOS
Reviewed-by: almatvee, erikj, herrick
1 parent 7a6c176 commit fac3c2d

File tree

16 files changed

+1042
-81
lines changed

16 files changed

+1042
-81
lines changed
 

‎make/modules/jdk.jpackage/Lib.gmk

+77-25
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,17 @@ include LibCommon.gmk
2828
################################################################################
2929

3030

31-
JPACKAGE_APPLAUNCHER_SRC := \
32-
$(call FindSrcDirsForComponent, jdk.jpackage, applauncher) \
33-
$(call FindSrcDirsForComponent, jdk.jpackage, common)
31+
ifeq ($(call isTargetOs, linux), true)
32+
JPACKAGE_APPLAUNCHER_SRC := \
33+
$(call FindSrcDirsForComponent, jdk.jpackage, applauncher)
34+
JPACKAGE_APPLAUNCHER_TOOLCHAIN := TOOLCHAIN_DEFAULT
35+
JPACKAGE_APPLAUNCHER_INCLUDE_FILES := %.c
36+
else
37+
JPACKAGE_APPLAUNCHER_SRC := \
38+
$(call FindSrcDirsForComponent, jdk.jpackage, applauncher) \
39+
$(call FindSrcDirsForComponent, jdk.jpackage, common)
40+
JPACKAGE_APPLAUNCHER_TOOLCHAIN := TOOLCHAIN_LINK_CXX
41+
endif
3442

3543

3644
ifeq ($(call isTargetOs, windows), true)
@@ -44,27 +52,63 @@ endif
4452

4553
JPACKAGE_OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/jpackage/internal/resources
4654
JPACKAGE_CXXFLAGS_windows := -EHsc -DUNICODE -D_UNICODE
55+
JPACKAGE_CFLAGS_windows := -DUNICODE -D_UNICODE
56+
JPACKAGE_APPLAUNCHER_INCLUDES := $(addprefix -I, $(JPACKAGE_APPLAUNCHER_SRC))
4757

4858
# Output app launcher executable in resources dir, and symbols in the object dir
4959
$(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHEREXE, \
5060
NAME := jpackageapplauncher, \
5161
OUTPUT_DIR := $(JPACKAGE_OUTPUT_DIR), \
5262
SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncher, \
5363
SRC := $(JPACKAGE_APPLAUNCHER_SRC), \
54-
TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
64+
INCLUDE_FILES := $(JPACKAGE_APPLAUNCHER_INCLUDE_FILES), \
65+
TOOLCHAIN := $(JPACKAGE_APPLAUNCHER_TOOLCHAIN), \
5566
OPTIMIZATION := LOW, \
5667
CXXFLAGS := $(call JpackageWithStaticCrt, $(CXXFLAGS_JDKEXE)) \
57-
$(addprefix -I, $(JPACKAGE_APPLAUNCHER_SRC)), \
68+
$(JPACKAGE_APPLAUNCHER_INCLUDES), \
69+
CFLAGS := $(call JpackageWithStaticCrt, $(CFLAGS_JDKEXE)) \
70+
$(JPACKAGE_APPLAUNCHER_INCLUDES), \
71+
CFLAGS_macosx := -Wno-format-nonliteral, \
5872
CXXFLAGS_windows := $(JPACKAGE_CXXFLAGS_windows), \
73+
CFLAGS_windows := $(JPACKAGE_CFLAGS_windows), \
5974
LDFLAGS := $(LDFLAGS_JDKEXE), \
60-
LIBS_macosx := -framework Cocoa, \
61-
LIBS := $(LIBCXX), \
62-
LIBS_linux := -ldl, \
75+
LIBS_macosx := $(LIBCXX) -framework Cocoa, \
76+
LIBS_windows := $(LIBCXX), \
77+
LIBS_linux := -nodefaultlibs -lc -ldl, \
6378
))
6479

65-
$(BUILD_JPACKAGE_APPLAUNCHEREXE): $(call FindLib, java.base, java)
80+
JPACKAGE_TARGETS += $(BUILD_JPACKAGE_APPLAUNCHEREXE)
81+
82+
83+
################################################################################
84+
85+
ifeq ($(call isTargetOs, linux), true)
86+
87+
JPACKAGE_LIBAPPLAUNCHER_SRC := \
88+
$(call FindSrcDirsForComponent, jdk.jpackage, applauncher) \
89+
$(call FindSrcDirsForComponent, jdk.jpackage, libapplauncher) \
90+
$(call FindSrcDirsForComponent, jdk.jpackage, common)
91+
92+
JPACKAGE_LIBAPPLAUNCHER_INCLUDES := $(addprefix -I, $(JPACKAGE_LIBAPPLAUNCHER_SRC))
93+
94+
$(eval $(call SetupJdkLibrary, BUILD_JPACKAGE_LIBAPPLAUNCHER, \
95+
NAME := jpackageapplauncher, \
96+
OUTPUT_DIR := $(JPACKAGE_OUTPUT_DIR), \
97+
SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjpackageapplauncher, \
98+
SRC := $(JPACKAGE_LIBAPPLAUNCHER_SRC), \
99+
EXCLUDE_FILES := LinuxLauncher.c LinuxPackage.c, \
100+
TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
101+
OPTIMIZATION := LOW, \
102+
CXXFLAGS := $(CXXFLAGS_JDKLIB) $(JPACKAGE_LIBAPPLAUNCHER_INCLUDES), \
103+
CFLAGS := $(CFLAGS_JDKLIB) $(JPACKAGE_LIBAPPLAUNCHER_INCLUDES), \
104+
LDFLAGS := $(LDFLAGS_JDKLIB), \
105+
LIBS := $(LIBCXX) -ldl, \
106+
))
107+
108+
JPACKAGE_TARGETS += $(BUILD_JPACKAGE_LIBAPPLAUNCHER)
109+
110+
endif
66111

67-
TARGETS += $(BUILD_JPACKAGE_APPLAUNCHEREXE)
68112

69113
################################################################################
70114

@@ -80,7 +124,7 @@ ifeq ($(call isTargetOs, windows), true)
80124
LIBS := $(LIBCXX), \
81125
))
82126

83-
TARGETS += $(BUILD_LIB_JPACKAGE)
127+
JPACKAGE_TARGETS += $(BUILD_LIB_JPACKAGE)
84128

85129
# Build Wix custom action helper
86130
# Output library in resources dir, and symbols in the object dir
@@ -96,7 +140,7 @@ ifeq ($(call isTargetOs, windows), true)
96140
LIBS_windows := msi.lib Shlwapi.lib User32.lib, \
97141
))
98142

99-
TARGETS += $(BUILD_LIB_WIXHELPER)
143+
JPACKAGE_TARGETS += $(BUILD_LIB_WIXHELPER)
100144

101145
JPACKAGE_MSIWRAPPER_SRC := \
102146
$(call FindSrcDirsForComponent, jdk.jpackage, msiwrapper) \
@@ -114,22 +158,30 @@ ifeq ($(call isTargetOs, windows), true)
114158
LIBS := $(LIBCXX), \
115159
))
116160

117-
TARGETS += $(BUILD_JPACKAGE_MSIWRAPPER)
161+
JPACKAGE_TARGETS += $(BUILD_JPACKAGE_MSIWRAPPER)
118162

119163
# Build non-console version of launcher
120164
$(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHERWEXE, \
121-
NAME := jpackageapplauncherw, \
122-
OUTPUT_DIR := $(JPACKAGE_OUTPUT_DIR), \
123-
SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncherw, \
124-
SRC := $(BUILD_JPACKAGE_APPLAUNCHEREXE_SRC), \
125-
TOOLCHAIN := $(BUILD_JPACKAGE_APPLAUNCHEREXE_TOOLCHAIN), \
126-
OPTIMIZATION := $(BUILD_JPACKAGE_APPLAUNCHEREXE_OPTIMIZATION), \
127-
CXXFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CXXFLAGS), \
128-
CXXFLAGS_windows := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CXXFLAGS_windows) -DJP_LAUNCHERW, \
129-
LDFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LDFLAGS), \
130-
LIBS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LIBS), \
131-
))
165+
NAME := jpackageapplauncherw, \
166+
OUTPUT_DIR := $(JPACKAGE_OUTPUT_DIR), \
167+
SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncherw, \
168+
SRC := $(BUILD_JPACKAGE_APPLAUNCHEREXE_SRC), \
169+
TOOLCHAIN := $(BUILD_JPACKAGE_APPLAUNCHEREXE_TOOLCHAIN), \
170+
OPTIMIZATION := $(BUILD_JPACKAGE_APPLAUNCHEREXE_OPTIMIZATION), \
171+
CXXFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CXXFLAGS), \
172+
CXXFLAGS_windows := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CXXFLAGS_windows) -DJP_LAUNCHERW, \
173+
CFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CFLAGS), \
174+
CFLAGS_windows := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CFLAGS_windows) -DJP_LAUNCHERW, \
175+
LDFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LDFLAGS), \
176+
LIBS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LIBS), \
177+
LIBS_windows := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LIBS_windows), \
178+
))
132179

133-
TARGETS += $(BUILD_JPACKAGE_APPLAUNCHERWEXE)
180+
JPACKAGE_TARGETS += $(BUILD_JPACKAGE_APPLAUNCHERWEXE)
134181

135182
endif
183+
184+
185+
TARGETS += $(JPACKAGE_TARGETS)
186+
187+
$(JPACKAGE_TARGETS): $(call FindLib, java.base, java)

‎src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxAppImageBuilder.java

+14
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ public void prepareApplicationFiles(Map<String, ? super Object> params)
8383
// create the primary launcher
8484
createLauncherForEntryPoint(params, null);
8585

86+
// create app launcher shared library
87+
createLauncherLib();
88+
8689
// create the additional launchers, if any
8790
List<Map<String, ? super Object>> entryPoints
8891
= ADD_LAUNCHERS.fetchFrom(params);
@@ -95,6 +98,17 @@ public void prepareApplicationFiles(Map<String, ? super Object> params)
9598
copyApplication(params);
9699
}
97100

101+
private void createLauncherLib() throws IOException {
102+
Path path = appLayout.pathGroup().getPath(
103+
ApplicationLayout.PathRole.LINUX_APPLAUNCHER_LIB);
104+
try (InputStream resource = getResourceAsStream("libjpackageapplauncher.so")) {
105+
writeEntry(resource, path);
106+
}
107+
108+
path.toFile().setExecutable(true, false);
109+
path.toFile().setWritable(true, true);
110+
}
111+
98112
private void createLauncherForEntryPoint(Map<String, ? super Object> params,
99113
Map<String, ? super Object> mainParams) throws IOException {
100114
// Copy executable to launchers folder
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
#include <stdio.h>
27+
#include <string.h>
28+
#include <stdlib.h>
29+
#include <dlfcn.h>
30+
#include <errno.h>
31+
#include <linux/limits.h>
32+
#include <unistd.h>
33+
#include <libgen.h>
34+
#include "JvmLauncher.h"
35+
#include "LinuxPackage.h"
36+
37+
38+
#define STATUS_FAILURE 1
39+
40+
typedef JvmlLauncherHandle (*JvmlLauncherAPI_CreateFunType)(int argc, char *argv[]);
41+
42+
static int appArgc;
43+
static char **appArgv;
44+
45+
46+
static JvmlLauncherData* initJvmlLauncherData(void) {
47+
char* launcherLibPath = 0;
48+
void* jvmLauncherLibHandle = 0;
49+
JvmlLauncherAPI_GetAPIFunc getApi = 0;
50+
JvmlLauncherAPI_CreateFunType createJvmlLauncher = 0;
51+
JvmlLauncherAPI* api = 0;
52+
JvmlLauncherHandle jvmLauncherHandle = 0;
53+
JvmlLauncherData* result = 0;
54+
55+
launcherLibPath = getJvmLauncherLibPath();
56+
if (!launcherLibPath) {
57+
goto cleanup;
58+
}
59+
60+
jvmLauncherLibHandle = dlopen(launcherLibPath, RTLD_NOW | RTLD_LOCAL);
61+
if (!jvmLauncherLibHandle) {
62+
JP_LOG_ERRMSG(dlerror());
63+
goto cleanup;
64+
}
65+
66+
getApi = dlsym(jvmLauncherLibHandle, "jvmLauncherGetAPI");
67+
if (!getApi) {
68+
JP_LOG_ERRMSG(dlerror());
69+
goto cleanup;
70+
}
71+
72+
api = (*getApi)();
73+
if (!api) {
74+
JP_LOG_ERRMSG("Failed to get JvmlLauncherAPI instance");
75+
goto cleanup;
76+
}
77+
78+
createJvmlLauncher = dlsym(jvmLauncherLibHandle, "jvmLauncherCreate");
79+
if (!createJvmlLauncher) {
80+
JP_LOG_ERRMSG(dlerror());
81+
goto cleanup;
82+
}
83+
84+
jvmLauncherHandle = (*createJvmlLauncher)(appArgc, appArgv);
85+
if (!jvmLauncherHandle) {
86+
goto cleanup;
87+
}
88+
89+
result = jvmLauncherCreateJvmlLauncherData(api, jvmLauncherHandle);
90+
/* Handle released in jvmLauncherCreateJvmlLauncherData() */
91+
jvmLauncherHandle = 0;
92+
93+
cleanup:
94+
if (jvmLauncherHandle) {
95+
jvmLauncherCloseHandle(api, jvmLauncherHandle);
96+
}
97+
if (jvmLauncherLibHandle) {
98+
dlclose(jvmLauncherLibHandle);
99+
}
100+
free(launcherLibPath);
101+
102+
return result;
103+
}
104+
105+
106+
static int launchJvm(JvmlLauncherData* cfg) {
107+
void* jliLibHandle = 0;
108+
void* JLI_Launch;
109+
int exitCode = STATUS_FAILURE;
110+
111+
jliLibHandle = dlopen(cfg->jliLibPath, RTLD_NOW | RTLD_LOCAL);
112+
if (!jliLibHandle) {
113+
JP_LOG_ERRMSG(dlerror());
114+
goto cleanup;
115+
}
116+
117+
JLI_Launch = dlsym(jliLibHandle, "JLI_Launch");
118+
if (!JLI_Launch) {
119+
JP_LOG_ERRMSG(dlerror());
120+
goto cleanup;
121+
}
122+
123+
exitCode = jvmLauncherStartJvm(cfg, JLI_Launch);
124+
125+
cleanup:
126+
if (jliLibHandle) {
127+
dlclose(jliLibHandle);
128+
}
129+
130+
return exitCode;
131+
}
132+
133+
134+
int main(int argc, char *argv[]) {
135+
int exitCode = STATUS_FAILURE;
136+
JvmlLauncherData* jvmLauncherData;
137+
138+
appArgc = argc;
139+
appArgv = argv;
140+
141+
jvmLauncherData = initJvmlLauncherData();
142+
if (jvmLauncherData) {
143+
exitCode = launchJvm(jvmLauncherData);
144+
free(jvmLauncherData);
145+
}
146+
147+
return exitCode;
148+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,336 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
#include <stdio.h>
27+
#include <string.h>
28+
#include <stdlib.h>
29+
#include <errno.h>
30+
#include <linux/limits.h>
31+
#include <unistd.h>
32+
#include <libgen.h>
33+
#include "JvmLauncher.h"
34+
#include "LinuxPackage.h"
35+
36+
37+
static char* getModulePath(void) {
38+
char modulePath[PATH_MAX] = { 0 };
39+
ssize_t modulePathLen = 0;
40+
char* result = 0;
41+
42+
modulePathLen = readlink("/proc/self/exe", modulePath,
43+
sizeof(modulePath) - 1);
44+
if (modulePathLen < 0) {
45+
JP_LOG_ERRNO;
46+
return 0;
47+
}
48+
modulePath[modulePathLen] = '\0';
49+
result = strdup(modulePath);
50+
if (!result) {
51+
JP_LOG_ERRNO;
52+
}
53+
54+
return result;
55+
}
56+
57+
58+
# define PACKAGE_TYPE_UNKNOWN 0
59+
# define PACKAGE_TYPE_RPM 1
60+
# define PACKAGE_TYPE_DEB 2
61+
62+
typedef struct {
63+
char* name;
64+
int type;
65+
} PackageDesc;
66+
67+
68+
static void freePackageDesc(PackageDesc* desc) {
69+
if (desc) {
70+
free(desc->name);
71+
free(desc);
72+
}
73+
}
74+
75+
76+
static PackageDesc* createPackageDesc(void) {
77+
PackageDesc* result = 0;
78+
79+
result = malloc(sizeof(PackageDesc));
80+
if (!result) {
81+
JP_LOG_ERRNO;
82+
goto cleanup;
83+
}
84+
85+
result->type = PACKAGE_TYPE_UNKNOWN;
86+
result->name = 0;
87+
88+
cleanup:
89+
return result;
90+
}
91+
92+
93+
static PackageDesc* initPackageDesc(PackageDesc* desc, const char* str,
94+
int type) {
95+
char *newStr = strdup(str);
96+
if (!newStr) {
97+
JP_LOG_ERRNO;
98+
return 0;
99+
}
100+
101+
free(desc->name);
102+
desc->name = newStr;
103+
desc->type = type;
104+
return desc;
105+
}
106+
107+
108+
#define POPEN_CALLBACK_USE 1
109+
#define POPEN_CALLBACK_IGNORE 0
110+
111+
typedef int (*popenCallbackType)(void*, const char*);
112+
113+
static int popenCommand(const char* cmdlineFormat, const char* arg,
114+
popenCallbackType callback, void* callbackData) {
115+
char* cmdline = 0;
116+
FILE *stream = 0;
117+
const size_t cmdlineLenth = strlen(cmdlineFormat) + strlen(arg);
118+
char* strBufBegin = 0;
119+
char* strBufEnd = 0;
120+
char* strBufNextChar = 0;
121+
char* strNewBufBegin = 0;
122+
size_t strBufCapacity = 0;
123+
int callbackMode = POPEN_CALLBACK_USE;
124+
int exitCode = -1;
125+
int c;
126+
127+
cmdline = malloc(cmdlineLenth + 1 /* \0 */);
128+
if (!cmdline) {
129+
JP_LOG_ERRNO;
130+
goto cleanup;
131+
}
132+
133+
#if defined(__GNUC__) && __GNUC__ >= 5
134+
#pragma GCC diagnostic push
135+
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
136+
#endif
137+
if (0 > snprintf(cmdline, cmdlineLenth, cmdlineFormat, arg)) {
138+
JP_LOG_ERRNO;
139+
goto cleanup;
140+
}
141+
#if defined(__GNUC__) && __GNUC__ >= 5
142+
#pragma GCC diagnostic pop
143+
#endif
144+
145+
JP_LOG_TRACE("popen: (%s)", cmdline);
146+
147+
stream = popen(cmdline, "r");
148+
if (!stream) {
149+
JP_LOG_ERRNO;
150+
goto cleanup;
151+
}
152+
153+
for (;;) {
154+
c = fgetc(stream);
155+
if((EOF == c || '\n' == c)) {
156+
if (POPEN_CALLBACK_USE == callbackMode
157+
&& strBufBegin != strBufNextChar) {
158+
*strBufNextChar = 0;
159+
JP_LOG_TRACE("popen: [%s]", strBufBegin);
160+
callbackMode = (*callback)(callbackData, strBufBegin);
161+
strBufNextChar = strBufBegin;
162+
}
163+
164+
if (EOF == c) {
165+
break;
166+
}
167+
168+
continue;
169+
}
170+
171+
if (strBufNextChar == strBufEnd) {
172+
/* Double buffer size */
173+
strBufCapacity = strBufCapacity * 2 + 1;
174+
strNewBufBegin = realloc(strBufBegin, strBufCapacity);
175+
if (!strNewBufBegin) {
176+
JP_LOG_ERRNO;
177+
goto cleanup;
178+
}
179+
180+
strBufNextChar = strNewBufBegin + (strBufNextChar - strBufBegin);
181+
strBufEnd = strNewBufBegin + strBufCapacity;
182+
strBufBegin = strNewBufBegin;
183+
}
184+
185+
*strBufNextChar++ = (char)c;
186+
}
187+
188+
cleanup:
189+
if (stream) {
190+
exitCode = pclose(stream);
191+
}
192+
193+
if (strBufBegin) {
194+
free(strBufBegin);
195+
}
196+
197+
free(cmdline);
198+
199+
JP_LOG_TRACE("popen: exit: %d", exitCode);
200+
return exitCode;
201+
}
202+
203+
204+
static char* concat(const char *x, const char *y) {
205+
const size_t lenX = strlen(x);
206+
const size_t lenY = strlen(y);
207+
208+
char *result = malloc(lenX + lenY + 1 /* \0 */);
209+
if (!result) {
210+
JP_LOG_ERRNO;
211+
} else {
212+
strcpy(result, x);
213+
strcat(result, y);
214+
}
215+
216+
return result;
217+
}
218+
219+
220+
static int initRpmPackage(void* desc, const char* str) {
221+
initPackageDesc((PackageDesc*)desc, str, PACKAGE_TYPE_RPM);
222+
return POPEN_CALLBACK_IGNORE;
223+
}
224+
225+
226+
static int initDebPackage(void* desc, const char* str) {
227+
char* colonChrPos = strchr(str, ':');
228+
if (colonChrPos) {
229+
*colonChrPos = 0;
230+
}
231+
initPackageDesc((PackageDesc*)desc, str, PACKAGE_TYPE_DEB);
232+
return POPEN_CALLBACK_IGNORE;
233+
}
234+
235+
236+
#define LAUNCHER_LIB_NAME "/libapplauncher.so"
237+
238+
static int findLauncherLib(void* launcherLibPath, const char* str) {
239+
char* buf = 0;
240+
const size_t strLen = strlen(str);
241+
const size_t launcherLibNameLen = strlen(LAUNCHER_LIB_NAME);
242+
243+
if (launcherLibNameLen <= strLen
244+
&& !strcmp(str + strLen - launcherLibNameLen, LAUNCHER_LIB_NAME)) {
245+
buf = strdup(str);
246+
if (!buf) {
247+
JP_LOG_ERRNO;
248+
} else {
249+
*(char**)launcherLibPath = buf;
250+
}
251+
return POPEN_CALLBACK_IGNORE;
252+
}
253+
return POPEN_CALLBACK_USE;
254+
}
255+
256+
257+
static PackageDesc* findOwnerOfFile(const char* path) {
258+
int popenStatus = -1;
259+
PackageDesc* pkg = 0;
260+
261+
pkg = createPackageDesc();
262+
if (!pkg) {
263+
return 0;
264+
}
265+
266+
popenStatus = popenCommand(
267+
"rpm --queryformat '%{NAME}' -qf '%s' 2>/dev/null", path,
268+
initRpmPackage, pkg);
269+
if (popenStatus) {
270+
pkg->type = PACKAGE_TYPE_UNKNOWN;
271+
popenStatus = popenCommand("dpkg -S '%s' 2>/dev/null", path,
272+
initDebPackage, pkg);
273+
}
274+
275+
if (popenStatus) {
276+
pkg->type = PACKAGE_TYPE_UNKNOWN;
277+
}
278+
279+
if (PACKAGE_TYPE_UNKNOWN == pkg->type || !pkg->name) {
280+
freePackageDesc(pkg);
281+
pkg = 0;
282+
}
283+
284+
if (pkg) {
285+
JP_LOG_TRACE("owner pkg: (%s|%d)", pkg->name, pkg->type);
286+
}
287+
288+
return pkg;
289+
}
290+
291+
292+
char* getJvmLauncherLibPath(void) {
293+
char* modulePath = 0;
294+
char* appImageDir = 0;
295+
char* launcherLibPath = 0;
296+
const char* pkgQueryCmd = 0;
297+
int popenStatus = -1;
298+
PackageDesc* pkg = 0;
299+
300+
modulePath = getModulePath();
301+
if (!modulePath) {
302+
goto cleanup;
303+
}
304+
305+
pkg = findOwnerOfFile(modulePath);
306+
if (!pkg) {
307+
/* Not a package install */
308+
/* Launcher should be in "bin" subdirectory of app image. */
309+
/* Launcher lib should be in "lib" subdirectory of app image. */
310+
appImageDir = dirname(dirname(modulePath));
311+
launcherLibPath = concat(appImageDir, "/lib" LAUNCHER_LIB_NAME);
312+
} else {
313+
if (PACKAGE_TYPE_RPM == pkg->type) {
314+
pkgQueryCmd = "rpm -ql '%s' 2>/dev/null";
315+
} else if (PACKAGE_TYPE_RPM == pkg->type) {
316+
pkgQueryCmd = "dpkg -L '%s' 2>/dev/null";
317+
} else {
318+
/* Should never happen */
319+
JP_LOG_ERRMSG("Internal error");
320+
goto cleanup;
321+
}
322+
323+
popenStatus = popenCommand(pkgQueryCmd, pkg->name, findLauncherLib,
324+
&launcherLibPath);
325+
if (popenStatus) {
326+
free(launcherLibPath);
327+
goto cleanup;
328+
}
329+
}
330+
331+
cleanup:
332+
free(modulePath);
333+
freePackageDesc(pkg);
334+
335+
return launcherLibPath;
336+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
#ifndef LinuxPackage_h
27+
#define LinuxPackage_h
28+
29+
#ifdef __cplusplus
30+
extern "C" {
31+
#endif
32+
33+
char* getJvmLauncherLibPath(void);
34+
35+
#ifdef __cplusplus
36+
}
37+
#endif
38+
39+
#endif /* #ifndef LinuxPackage_h */

‎src/jdk.jpackage/linux/native/applauncher/LinuxLauncher.cpp ‎src/jdk.jpackage/linux/native/libapplauncher/LinuxLauncherLib.cpp

+34-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -23,8 +23,10 @@
2323
* questions.
2424
*/
2525

26-
#include <stdio.h>
27-
#include <stdlib.h>
26+
#include "kludge_c++11.h"
27+
28+
#include <memory>
29+
#include "JvmLauncher.h"
2830
#include "AppLauncher.h"
2931
#include "FileUtils.h"
3032
#include "UnixSysInfo.h"
@@ -44,6 +46,8 @@ size_t hash(const std::string& str) {
4446
return h;
4547
}
4648

49+
Jvm* jvmLauncher;
50+
4751
void launchApp() {
4852
const tstring launcherPath = SysInfo::getProcessModulePath();
4953

@@ -116,14 +120,38 @@ void launchApp() {
116120
}
117121
JP_CATCH_ALL;
118122

119-
appLauncher.launch();
123+
jvmLauncher = appLauncher.createJvmLauncher();
120124
}
121125

122126
} // namespace
123127

124128

125-
int main(int argc, char *argv[]) {
129+
extern "C" {
130+
131+
JNIEXPORT JvmlLauncherHandle jvmLauncherCreate(int argc, char *argv[]) {
126132
SysInfo::argc = argc;
127133
SysInfo::argv = argv;
128-
return app::launch(std::nothrow, launchApp);
134+
jvmLauncher = 0;
135+
app::launch(std::nothrow, launchApp);
136+
137+
JvmlLauncherHandle jlh = 0;
138+
if (jvmLauncher) {
139+
jlh = jvmLauncher->exportLauncher();
140+
const std::unique_ptr<Jvm> deleter(jvmLauncher);
141+
}
142+
143+
return jlh;
129144
}
145+
146+
} // extern "C"
147+
148+
149+
namespace {
150+
151+
void dcon() __attribute__((destructor));
152+
153+
void dcon() {
154+
LOG_TRACE("unload");
155+
}
156+
157+
} // namespace

‎src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationLayout.java

+10-2
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ enum PathRole {
6262
* Directory with application Java modules.
6363
*/
6464
MODULES,
65+
66+
/**
67+
* Linux app launcher shared library.
68+
*/
69+
LINUX_APPLAUNCHER_LIB
6570
}
6671

6772
ApplicationLayout(Map<Object, Path> paths) {
@@ -131,7 +136,8 @@ static ApplicationLayout linuxAppImage() {
131136
PathRole.RUNTIME, Path.of("lib/runtime"),
132137
PathRole.RUNTIME_HOME, Path.of("lib/runtime"),
133138
PathRole.DESKTOP, Path.of("lib"),
134-
PathRole.MODULES, Path.of("lib/app/mods")
139+
PathRole.MODULES, Path.of("lib/app/mods"),
140+
PathRole.LINUX_APPLAUNCHER_LIB, Path.of("lib/libapplauncher.so")
135141
));
136142
}
137143

@@ -186,7 +192,9 @@ public static ApplicationLayout linuxUsrTreePackageImage(Path prefix,
186192
PathRole.RUNTIME, lib.resolve("runtime"),
187193
PathRole.RUNTIME_HOME, lib.resolve("runtime"),
188194
PathRole.DESKTOP, lib,
189-
PathRole.MODULES, lib.resolve("app/mods")
195+
PathRole.MODULES, lib.resolve("app/mods"),
196+
PathRole.LINUX_APPLAUNCHER_LIB, lib.resolve(
197+
"lib/libapplauncher.so")
190198
));
191199
}
192200

‎src/jdk.jpackage/share/native/applauncher/JvmLauncher.cpp

+178-46
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
*/
2525

2626
#include <cstring>
27-
#include <jni.h>
27+
#include "tstrings.h"
2828
#include "JvmLauncher.h"
2929
#include "Log.h"
3030
#include "Dll.h"
@@ -39,6 +39,16 @@
3939
#define LAUNCH_FUNC "JLI_Launch"
4040
#endif
4141

42+
Jvm::Jvm() {
43+
LOG_TRACE(tstrings::any() << "Jvm(" << this << ")::Jvm()");
44+
}
45+
46+
47+
Jvm::~Jvm() {
48+
LOG_TRACE(tstrings::any() << "Jvm(" << this << ")::~Jvm()");
49+
}
50+
51+
4252
Jvm& Jvm::initFromConfigFile(const CfgFile& cfgFile) {
4353
const CfgFile::Properties& appOptions = cfgFile.getProperties(
4454
SectionName::Application);
@@ -160,69 +170,191 @@ bool Jvm::isWithSplash() const {
160170

161171

162172
namespace {
163-
void convertArgs(const std::vector<std::string>& args, std::vector<char*>& argv) {
164-
argv.reserve(args.size() + 1);
165-
argv.resize(0);
166173

167-
std::vector<std::string>::const_iterator it = args.begin();
168-
const std::vector<std::string>::const_iterator end = args.end();
174+
struct JvmlLauncherHandleCloser {
175+
typedef JvmlLauncherHandle pointer;
169176

170-
for (; it != end; ++it) {
171-
argv.push_back(const_cast<char*>(it->c_str()));
172-
};
177+
void operator()(JvmlLauncherHandle h) {
178+
jvmLauncherCloseHandle(jvmLauncherGetAPI(), h);
179+
}
180+
};
181+
182+
struct JvmlLauncherDataDeleter {
183+
typedef JvmlLauncherData* pointer;
184+
185+
void operator()(JvmlLauncherData* ptr) {
186+
free(ptr);
187+
}
188+
};
173189

174-
// Add treminal '0'.
175-
argv.push_back(0);
176-
}
177190
} // namespace
178191

179192
void Jvm::launch() {
180-
typedef int (JNICALL *LaunchFuncType)(int argc, char ** argv,
181-
int jargc, const char** jargv,
182-
int appclassc, const char** appclassv,
183-
const char* fullversion,
184-
const char* dotversion,
185-
const char* pname,
186-
const char* lname,
187-
jboolean javaargs,
188-
jboolean cpwildcard,
189-
jboolean javaw,
190-
jint ergo);
191-
192-
std::vector<char*> argv;
193+
typedef std::unique_ptr<
194+
JvmlLauncherHandle, JvmlLauncherHandleCloser> AutoJvmlLauncherHandle;
195+
196+
typedef std::unique_ptr<
197+
JvmlLauncherData, JvmlLauncherDataDeleter> AutoJvmlLauncherData;
198+
199+
AutoJvmlLauncherHandle jlh(exportLauncher());
200+
201+
JvmlLauncherAPI* api = jvmLauncherGetAPI();
202+
203+
AutoJvmlLauncherData jld(jvmLauncherCreateJvmlLauncherData(api,
204+
jlh.release()));
205+
206+
LOG_TRACE(tstrings::any() << "JVM library: \"" << jvmPath << "\"");
207+
208+
DllFunction<void*> func(Dll(jvmPath), LAUNCH_FUNC);
209+
210+
int exitStatus = jvmLauncherStartJvm(jld.get(), func.operator void*());
211+
212+
if (exitStatus != 0) {
213+
JP_THROW("Failed to launch JVM");
214+
}
215+
}
216+
217+
218+
namespace {
219+
220+
struct JliLaunchData {
221+
std::string jliLibPath;
222+
std::vector<std::string> args;
223+
224+
int initJvmlLauncherData(JvmlLauncherData* ptr, int bufferSize) const {
225+
int minimalBufferSize = initJvmlLauncherData(0);
226+
if (minimalBufferSize <= bufferSize) {
227+
initJvmlLauncherData(ptr);
228+
}
229+
return minimalBufferSize;
230+
}
231+
232+
private:
233+
int initJvmlLauncherData(JvmlLauncherData* ptr) const {
234+
// Store path to JLI library just behind JvmlLauncherData header.
235+
char* curPtr = reinterpret_cast<char*>(ptr + 1);
236+
do {
237+
const size_t count = sizeof(char)
238+
* (jliLibPath.size() + 1 /* trailing zero */);
239+
if (ptr) {
240+
std::memcpy(curPtr, jliLibPath.c_str(), count);
241+
ptr->jliLibPath = curPtr;
242+
}
243+
curPtr += count;
244+
} while (false);
245+
246+
// Next write array of char* pointing to JLI lib arg strings.
247+
if (ptr) {
248+
ptr->jliLaunchArgv = reinterpret_cast<char**>(curPtr);
249+
ptr->jliLaunchArgc = (int)args.size();
250+
// Add terminal '0' arg.
251+
ptr->jliLaunchArgv[ptr->jliLaunchArgc] = 0;
252+
}
253+
254+
// Skip memory occupied by char* array.
255+
curPtr += sizeof(char*) * (args.size() + 1 /* terminal '0' arg */);
256+
257+
// Store array of strings.
258+
for (size_t i = 0; i != args.size(); i++) {
259+
const size_t count = (args[i].size() + 1 /* trailing zero */);
260+
if (ptr) {
261+
std::memcpy(curPtr, args[i].c_str(), count);
262+
ptr->jliLaunchArgv[i] = curPtr;
263+
}
264+
curPtr += count;
265+
};
266+
267+
const size_t bufferSize = curPtr - reinterpret_cast<char*>(ptr);
268+
if (ptr) {
269+
LOG_TRACE(tstrings::any() << "Initialized " << bufferSize
270+
<< " bytes at " << ptr << " address");
271+
} else {
272+
LOG_TRACE(tstrings::any() << "Need " << bufferSize
273+
<< " bytes for JvmlLauncherData buffer");
274+
}
275+
return static_cast<int>(bufferSize);
276+
}
277+
};
278+
279+
} // namespace
280+
281+
JvmlLauncherHandle Jvm::exportLauncher() const {
282+
std::unique_ptr<JliLaunchData> result(new JliLaunchData());
283+
284+
result->jliLibPath = tstrings::toUtf8(jvmPath);
285+
193286
#ifdef TSTRINGS_WITH_WCHAR
194-
std::vector<std::string> mbcs_args;
195287
do {
196288
tstring_array::const_iterator it = args.begin();
197289
const tstring_array::const_iterator end = args.end();
198290
for (; it != end; ++it) {
199-
mbcs_args.push_back(tstrings::toACP(*it));
291+
result->args.push_back(tstrings::toACP(*it));
200292
}
201293
} while (0);
202-
convertArgs(mbcs_args, argv);
203294
#else
204-
convertArgs(args, argv);
295+
result->args = args;
205296
#endif
206297

207-
// Don't count terminal '0'.
208-
const int argc = (int)argv.size() - 1;
298+
return result.release();
299+
}
209300

210-
LOG_TRACE(tstrings::any() << "JVM library: \"" << jvmPath << "\"");
211301

212-
DllFunction<LaunchFuncType> func(Dll(jvmPath), LAUNCH_FUNC);
213-
int exitStatus = func(argc, argv.data(),
214-
0, 0,
215-
0, 0,
216-
"",
217-
"",
218-
"java",
219-
"java",
220-
JNI_FALSE,
221-
JNI_FALSE,
222-
JNI_FALSE,
223-
0);
302+
namespace {
224303

225-
if (exitStatus != 0) {
226-
JP_THROW("Failed to launch JVM");
304+
void closeHandle(JvmlLauncherHandle h) {
305+
JP_TRY;
306+
307+
JliLaunchData* data = static_cast<JliLaunchData*>(h);
308+
const std::unique_ptr<JliLaunchData> deleter(data);
309+
310+
JP_CATCH_ALL;
311+
}
312+
313+
314+
int getJvmlLauncherDataSize(JvmlLauncherHandle h) {
315+
JP_TRY;
316+
317+
const JliLaunchData* data = static_cast<const JliLaunchData*>(h);
318+
return data->initJvmlLauncherData(0, 0);
319+
320+
JP_CATCH_ALL;
321+
322+
return -1;
323+
}
324+
325+
326+
JvmlLauncherData* initJvmlLauncherData(JvmlLauncherHandle h,
327+
void* ptr, int bufferSize) {
328+
JP_TRY;
329+
330+
const JliLaunchData* data = static_cast<const JliLaunchData*>(h);
331+
const int usedBufferSize = data->initJvmlLauncherData(
332+
static_cast<JvmlLauncherData*>(ptr), bufferSize);
333+
if (bufferSize <= usedBufferSize) {
334+
return static_cast<JvmlLauncherData*>(ptr);
335+
}
336+
337+
JP_CATCH_ALL;
338+
339+
return 0;
340+
}
341+
342+
class Impl : public JvmlLauncherAPI {
343+
public:
344+
Impl() {
345+
this->closeHandle = ::closeHandle;
346+
this->getJvmlLauncherDataSize = ::getJvmlLauncherDataSize;
347+
this->initJvmlLauncherData = ::initJvmlLauncherData;
227348
}
349+
} api;
350+
351+
} // namespace
352+
353+
354+
extern "C" {
355+
356+
JNIEXPORT JvmlLauncherAPI* jvmLauncherGetAPI(void) {
357+
return &api;
228358
}
359+
360+
} // extern "C"

‎src/jdk.jpackage/share/native/applauncher/JvmLauncher.h

+68
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,77 @@
2727
#ifndef JvmLauncher_h
2828
#define JvmLauncher_h
2929

30+
31+
#include "jni.h" /* JNIEXPORT */
32+
33+
34+
#ifdef __cplusplus
35+
extern "C" {
36+
#endif
37+
38+
typedef struct {
39+
const char* jliLibPath;
40+
int jliLaunchArgc;
41+
char** jliLaunchArgv;
42+
} JvmlLauncherData;
43+
44+
typedef void* JvmlLauncherHandle;
45+
46+
typedef void (*JvmlLauncherAPI_CloseHandleFunc)(JvmlLauncherHandle);
47+
typedef int (*JvmlLauncherAPI_GetJvmlLauncherDataSizeFunc)(JvmlLauncherHandle);
48+
typedef JvmlLauncherData* (*JvmlLauncherAPI_InitJvmlLauncherDataFunc)(JvmlLauncherHandle, void*, int);
49+
50+
typedef struct {
51+
JvmlLauncherAPI_CloseHandleFunc closeHandle;
52+
JvmlLauncherAPI_GetJvmlLauncherDataSizeFunc getJvmlLauncherDataSize;
53+
JvmlLauncherAPI_InitJvmlLauncherDataFunc initJvmlLauncherData;
54+
} JvmlLauncherAPI;
55+
56+
typedef JvmlLauncherAPI* (*JvmlLauncherAPI_GetAPIFunc)(void);
57+
58+
JNIEXPORT JvmlLauncherAPI* jvmLauncherGetAPI(void);
59+
60+
static inline void jvmLauncherCloseHandle(JvmlLauncherAPI* api, JvmlLauncherHandle h) {
61+
(*api->closeHandle)(h);
62+
}
63+
64+
static inline int jvmLauncherGetJvmlLauncherDataSize(JvmlLauncherAPI* api,
65+
JvmlLauncherHandle h) {
66+
return (*api->getJvmlLauncherDataSize)(h);
67+
}
68+
69+
static inline JvmlLauncherData* jvmLauncherInitJvmlLauncherData(JvmlLauncherAPI* api,
70+
JvmlLauncherHandle h, void* ptr, int bufferSize) {
71+
return (*api->initJvmlLauncherData)(h, ptr, bufferSize);
72+
}
73+
74+
JvmlLauncherData* jvmLauncherCreateJvmlLauncherData(JvmlLauncherAPI* api, JvmlLauncherHandle h);
75+
int jvmLauncherStartJvm(JvmlLauncherData* jvmArgs, void* JLI_Launch);
76+
77+
void jvmLauncherLog(const char* format, ...);
78+
79+
#define JP_LOG_ERRMSG(msg) do { jvmLauncherLog((msg)); } while (0)
80+
#define JP_LOG_ERRNO JP_LOG_ERRMSG(strerror(errno))
81+
#define JP_LOG_TRACE jvmLauncherLog
82+
83+
84+
#ifdef __cplusplus
85+
}
86+
#endif
87+
88+
89+
#ifdef __cplusplus
90+
3091
#include "tstrings.h"
3192

3293
class CfgFile;
3394

3495

3596
class Jvm {
3697
public:
98+
Jvm();
99+
~Jvm();
100+
37101
Jvm& initFromConfigFile(const CfgFile& cfgFile);
38102

39103
Jvm& addArgument(const tstring& value) {
@@ -54,9 +118,13 @@ class Jvm {
54118

55119
void launch();
56120

121+
JvmlLauncherHandle exportLauncher() const;
122+
57123
private:
58124
tstring jvmPath;
59125
tstring_array args;
60126
};
61127

128+
#endif // #ifdef __cplusplus
129+
62130
#endif // JvmLauncher_h
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
#include <string.h>
27+
#include <stdlib.h>
28+
#include <errno.h>
29+
30+
#include "JvmLauncher.h"
31+
32+
33+
typedef int (JNICALL *JLI_LaunchFuncType)(int argc, char ** argv,
34+
int jargc, const char** jargv,
35+
int appclassc, const char** appclassv,
36+
const char* fullversion,
37+
const char* dotversion,
38+
const char* pname,
39+
const char* lname,
40+
jboolean javaargs,
41+
jboolean cpwildcard,
42+
jboolean javaw,
43+
jint ergo);
44+
45+
46+
JvmlLauncherData* jvmLauncherCreateJvmlLauncherData(
47+
JvmlLauncherAPI* api, JvmlLauncherHandle h) {
48+
JvmlLauncherData* result = 0;
49+
void* buf = 0;
50+
int jvmLauncherDataBufferSize;
51+
52+
if (!h) {
53+
return 0;
54+
}
55+
56+
jvmLauncherDataBufferSize = jvmLauncherGetJvmlLauncherDataSize(api, h);
57+
if (jvmLauncherDataBufferSize <= 0) {
58+
goto cleanup;
59+
}
60+
61+
buf = malloc(jvmLauncherDataBufferSize);
62+
if (!buf) {
63+
JP_LOG_ERRNO;
64+
goto cleanup;
65+
}
66+
67+
result = jvmLauncherInitJvmlLauncherData(api, h, buf,
68+
jvmLauncherDataBufferSize);
69+
if (result) {
70+
/* Don't free the buffer in clean up. */
71+
buf = 0;
72+
}
73+
74+
cleanup:
75+
jvmLauncherCloseHandle(api, h);
76+
free(buf);
77+
78+
return result;
79+
}
80+
81+
82+
static void dumpJvmlLauncherData(const JvmlLauncherData* jvmArgs) {
83+
int i = 0;
84+
JP_LOG_TRACE("jli lib: [%s]", jvmArgs->jliLibPath);
85+
for (i = 0; i < jvmArgs->jliLaunchArgc; ++i) {
86+
JP_LOG_TRACE("jli arg[%d]: [%s]", i, jvmArgs->jliLaunchArgv[i]);
87+
}
88+
}
89+
90+
91+
int jvmLauncherStartJvm(JvmlLauncherData* jvmArgs, void* JLI_Launch) {
92+
int exitCode;
93+
94+
dumpJvmlLauncherData(jvmArgs);
95+
exitCode = (*((JLI_LaunchFuncType)JLI_Launch))(
96+
jvmArgs->jliLaunchArgc, jvmArgs->jliLaunchArgv,
97+
0, 0,
98+
0, 0,
99+
"",
100+
"",
101+
"java",
102+
"java",
103+
JNI_FALSE,
104+
JNI_FALSE,
105+
JNI_FALSE,
106+
0);
107+
108+
return exitCode;
109+
}
110+
111+
112+
void jvmLauncherLog(const char* format, ...) {
113+
const char *withLog = getenv("JPACKAGE_DEBUG");
114+
if (!withLog || strcmp(withLog, "true")) {
115+
return;
116+
}
117+
118+
va_list args;
119+
va_start(args, format);
120+
121+
#if defined(__GNUC__) && __GNUC__ >= 5
122+
#pragma GCC diagnostic push
123+
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
124+
#endif
125+
vfprintf(stderr, format, args);
126+
fprintf(stderr, "\n");
127+
#if defined(__GNUC__) && __GNUC__ >= 5
128+
#pragma GCC diagnostic pop
129+
#endif
130+
131+
va_end (args);
132+
}

‎src/jdk.jpackage/share/native/common/app.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
* questions.
2424
*/
2525

26+
#include "kludge_c++11.h"
27+
2628
#include <memory>
2729
#include "app.h"
2830
#include "Log.h"
@@ -56,6 +58,8 @@ class LastErrorLogAppender : public LogAppender {
5658

5759
class ResetLastErrorMsgAtEndOfScope {
5860
public:
61+
ResetLastErrorMsgAtEndOfScope() {
62+
}
5963
~ResetLastErrorMsgAtEndOfScope() {
6064
JP_NO_THROW(theLastErrorMsg = 0);
6165
}

‎src/jdk.jpackage/share/native/common/tstrings.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,13 @@ tstring unsafe_format(tstring::const_pointer format, ...) {
5252
#ifdef _MSC_VER
5353
ret = _vsntprintf_s(&*fmtout.begin(), fmtout.size(), _TRUNCATE, format, args);
5454
#else
55-
#ifdef __GNUC__
55+
#if defined(__GNUC__) && __GNUC__ >= 5
5656
#pragma GCC diagnostic push
5757
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
5858
#endif
5959
// With g++ this compiles only with '-std=gnu++0x' option
6060
ret = vsnprintf(&*fmtout.begin(), fmtout.size(), format, args);
61-
#ifdef __GNUC__
61+
#if defined(__GNUC__) && __GNUC__ >= 5
6262
#pragma GCC diagnostic pop
6363
#endif
6464
#endif

0 commit comments

Comments
 (0)
Please sign in to comment.