8254702: jpackage app launcher crashes on CentOS
Reviewed-by: almatvee, erikj, herrick
This commit is contained in:
parent
7a6c176845
commit
fac3c2d258
@ -28,9 +28,17 @@ include LibCommon.gmk
|
||||
################################################################################
|
||||
|
||||
|
||||
JPACKAGE_APPLAUNCHER_SRC := \
|
||||
$(call FindSrcDirsForComponent, jdk.jpackage, applauncher) \
|
||||
$(call FindSrcDirsForComponent, jdk.jpackage, common)
|
||||
ifeq ($(call isTargetOs, linux), true)
|
||||
JPACKAGE_APPLAUNCHER_SRC := \
|
||||
$(call FindSrcDirsForComponent, jdk.jpackage, applauncher)
|
||||
JPACKAGE_APPLAUNCHER_TOOLCHAIN := TOOLCHAIN_DEFAULT
|
||||
JPACKAGE_APPLAUNCHER_INCLUDE_FILES := %.c
|
||||
else
|
||||
JPACKAGE_APPLAUNCHER_SRC := \
|
||||
$(call FindSrcDirsForComponent, jdk.jpackage, applauncher) \
|
||||
$(call FindSrcDirsForComponent, jdk.jpackage, common)
|
||||
JPACKAGE_APPLAUNCHER_TOOLCHAIN := TOOLCHAIN_LINK_CXX
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(call isTargetOs, windows), true)
|
||||
@ -44,6 +52,8 @@ endif
|
||||
|
||||
JPACKAGE_OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/jpackage/internal/resources
|
||||
JPACKAGE_CXXFLAGS_windows := -EHsc -DUNICODE -D_UNICODE
|
||||
JPACKAGE_CFLAGS_windows := -DUNICODE -D_UNICODE
|
||||
JPACKAGE_APPLAUNCHER_INCLUDES := $(addprefix -I, $(JPACKAGE_APPLAUNCHER_SRC))
|
||||
|
||||
# Output app launcher executable in resources dir, and symbols in the object dir
|
||||
$(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHEREXE, \
|
||||
@ -51,20 +61,54 @@ $(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHEREXE, \
|
||||
OUTPUT_DIR := $(JPACKAGE_OUTPUT_DIR), \
|
||||
SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncher, \
|
||||
SRC := $(JPACKAGE_APPLAUNCHER_SRC), \
|
||||
TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
|
||||
INCLUDE_FILES := $(JPACKAGE_APPLAUNCHER_INCLUDE_FILES), \
|
||||
TOOLCHAIN := $(JPACKAGE_APPLAUNCHER_TOOLCHAIN), \
|
||||
OPTIMIZATION := LOW, \
|
||||
CXXFLAGS := $(call JpackageWithStaticCrt, $(CXXFLAGS_JDKEXE)) \
|
||||
$(addprefix -I, $(JPACKAGE_APPLAUNCHER_SRC)), \
|
||||
$(JPACKAGE_APPLAUNCHER_INCLUDES), \
|
||||
CFLAGS := $(call JpackageWithStaticCrt, $(CFLAGS_JDKEXE)) \
|
||||
$(JPACKAGE_APPLAUNCHER_INCLUDES), \
|
||||
CFLAGS_macosx := -Wno-format-nonliteral, \
|
||||
CXXFLAGS_windows := $(JPACKAGE_CXXFLAGS_windows), \
|
||||
CFLAGS_windows := $(JPACKAGE_CFLAGS_windows), \
|
||||
LDFLAGS := $(LDFLAGS_JDKEXE), \
|
||||
LIBS_macosx := -framework Cocoa, \
|
||||
LIBS := $(LIBCXX), \
|
||||
LIBS_linux := -ldl, \
|
||||
LIBS_macosx := $(LIBCXX) -framework Cocoa, \
|
||||
LIBS_windows := $(LIBCXX), \
|
||||
LIBS_linux := -nodefaultlibs -lc -ldl, \
|
||||
))
|
||||
|
||||
$(BUILD_JPACKAGE_APPLAUNCHEREXE): $(call FindLib, java.base, java)
|
||||
JPACKAGE_TARGETS += $(BUILD_JPACKAGE_APPLAUNCHEREXE)
|
||||
|
||||
|
||||
################################################################################
|
||||
|
||||
ifeq ($(call isTargetOs, linux), true)
|
||||
|
||||
JPACKAGE_LIBAPPLAUNCHER_SRC := \
|
||||
$(call FindSrcDirsForComponent, jdk.jpackage, applauncher) \
|
||||
$(call FindSrcDirsForComponent, jdk.jpackage, libapplauncher) \
|
||||
$(call FindSrcDirsForComponent, jdk.jpackage, common)
|
||||
|
||||
JPACKAGE_LIBAPPLAUNCHER_INCLUDES := $(addprefix -I, $(JPACKAGE_LIBAPPLAUNCHER_SRC))
|
||||
|
||||
$(eval $(call SetupJdkLibrary, BUILD_JPACKAGE_LIBAPPLAUNCHER, \
|
||||
NAME := jpackageapplauncher, \
|
||||
OUTPUT_DIR := $(JPACKAGE_OUTPUT_DIR), \
|
||||
SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjpackageapplauncher, \
|
||||
SRC := $(JPACKAGE_LIBAPPLAUNCHER_SRC), \
|
||||
EXCLUDE_FILES := LinuxLauncher.c LinuxPackage.c, \
|
||||
TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
|
||||
OPTIMIZATION := LOW, \
|
||||
CXXFLAGS := $(CXXFLAGS_JDKLIB) $(JPACKAGE_LIBAPPLAUNCHER_INCLUDES), \
|
||||
CFLAGS := $(CFLAGS_JDKLIB) $(JPACKAGE_LIBAPPLAUNCHER_INCLUDES), \
|
||||
LDFLAGS := $(LDFLAGS_JDKLIB), \
|
||||
LIBS := $(LIBCXX) -ldl, \
|
||||
))
|
||||
|
||||
JPACKAGE_TARGETS += $(BUILD_JPACKAGE_LIBAPPLAUNCHER)
|
||||
|
||||
endif
|
||||
|
||||
TARGETS += $(BUILD_JPACKAGE_APPLAUNCHEREXE)
|
||||
|
||||
################################################################################
|
||||
|
||||
@ -80,7 +124,7 @@ ifeq ($(call isTargetOs, windows), true)
|
||||
LIBS := $(LIBCXX), \
|
||||
))
|
||||
|
||||
TARGETS += $(BUILD_LIB_JPACKAGE)
|
||||
JPACKAGE_TARGETS += $(BUILD_LIB_JPACKAGE)
|
||||
|
||||
# Build Wix custom action helper
|
||||
# Output library in resources dir, and symbols in the object dir
|
||||
@ -96,7 +140,7 @@ ifeq ($(call isTargetOs, windows), true)
|
||||
LIBS_windows := msi.lib Shlwapi.lib User32.lib, \
|
||||
))
|
||||
|
||||
TARGETS += $(BUILD_LIB_WIXHELPER)
|
||||
JPACKAGE_TARGETS += $(BUILD_LIB_WIXHELPER)
|
||||
|
||||
JPACKAGE_MSIWRAPPER_SRC := \
|
||||
$(call FindSrcDirsForComponent, jdk.jpackage, msiwrapper) \
|
||||
@ -114,22 +158,30 @@ ifeq ($(call isTargetOs, windows), true)
|
||||
LIBS := $(LIBCXX), \
|
||||
))
|
||||
|
||||
TARGETS += $(BUILD_JPACKAGE_MSIWRAPPER)
|
||||
JPACKAGE_TARGETS += $(BUILD_JPACKAGE_MSIWRAPPER)
|
||||
|
||||
# Build non-console version of launcher
|
||||
$(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHERWEXE, \
|
||||
NAME := jpackageapplauncherw, \
|
||||
OUTPUT_DIR := $(JPACKAGE_OUTPUT_DIR), \
|
||||
SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncherw, \
|
||||
SRC := $(BUILD_JPACKAGE_APPLAUNCHEREXE_SRC), \
|
||||
TOOLCHAIN := $(BUILD_JPACKAGE_APPLAUNCHEREXE_TOOLCHAIN), \
|
||||
OPTIMIZATION := $(BUILD_JPACKAGE_APPLAUNCHEREXE_OPTIMIZATION), \
|
||||
CXXFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CXXFLAGS), \
|
||||
CXXFLAGS_windows := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CXXFLAGS_windows) -DJP_LAUNCHERW, \
|
||||
LDFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LDFLAGS), \
|
||||
LIBS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LIBS), \
|
||||
))
|
||||
NAME := jpackageapplauncherw, \
|
||||
OUTPUT_DIR := $(JPACKAGE_OUTPUT_DIR), \
|
||||
SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncherw, \
|
||||
SRC := $(BUILD_JPACKAGE_APPLAUNCHEREXE_SRC), \
|
||||
TOOLCHAIN := $(BUILD_JPACKAGE_APPLAUNCHEREXE_TOOLCHAIN), \
|
||||
OPTIMIZATION := $(BUILD_JPACKAGE_APPLAUNCHEREXE_OPTIMIZATION), \
|
||||
CXXFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CXXFLAGS), \
|
||||
CXXFLAGS_windows := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CXXFLAGS_windows) -DJP_LAUNCHERW, \
|
||||
CFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CFLAGS), \
|
||||
CFLAGS_windows := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CFLAGS_windows) -DJP_LAUNCHERW, \
|
||||
LDFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LDFLAGS), \
|
||||
LIBS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LIBS), \
|
||||
LIBS_windows := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LIBS_windows), \
|
||||
))
|
||||
|
||||
TARGETS += $(BUILD_JPACKAGE_APPLAUNCHERWEXE)
|
||||
JPACKAGE_TARGETS += $(BUILD_JPACKAGE_APPLAUNCHERWEXE)
|
||||
|
||||
endif
|
||||
|
||||
|
||||
TARGETS += $(JPACKAGE_TARGETS)
|
||||
|
||||
$(JPACKAGE_TARGETS): $(call FindLib, java.base, java)
|
||||
|
@ -83,6 +83,9 @@ public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
|
||||
// create the primary launcher
|
||||
createLauncherForEntryPoint(params, null);
|
||||
|
||||
// create app launcher shared library
|
||||
createLauncherLib();
|
||||
|
||||
// create the additional launchers, if any
|
||||
List<Map<String, ? super Object>> entryPoints
|
||||
= ADD_LAUNCHERS.fetchFrom(params);
|
||||
@ -95,6 +98,17 @@ public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
|
||||
copyApplication(params);
|
||||
}
|
||||
|
||||
private void createLauncherLib() throws IOException {
|
||||
Path path = appLayout.pathGroup().getPath(
|
||||
ApplicationLayout.PathRole.LINUX_APPLAUNCHER_LIB);
|
||||
try (InputStream resource = getResourceAsStream("libjpackageapplauncher.so")) {
|
||||
writeEntry(resource, path);
|
||||
}
|
||||
|
||||
path.toFile().setExecutable(true, false);
|
||||
path.toFile().setWritable(true, true);
|
||||
}
|
||||
|
||||
private void createLauncherForEntryPoint(Map<String, ? super Object> params,
|
||||
Map<String, ? super Object> mainParams) throws IOException {
|
||||
// Copy executable to launchers folder
|
||||
|
148
src/jdk.jpackage/linux/native/applauncher/LinuxLauncher.c
Normal file
148
src/jdk.jpackage/linux/native/applauncher/LinuxLauncher.c
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <linux/limits.h>
|
||||
#include <unistd.h>
|
||||
#include <libgen.h>
|
||||
#include "JvmLauncher.h"
|
||||
#include "LinuxPackage.h"
|
||||
|
||||
|
||||
#define STATUS_FAILURE 1
|
||||
|
||||
typedef JvmlLauncherHandle (*JvmlLauncherAPI_CreateFunType)(int argc, char *argv[]);
|
||||
|
||||
static int appArgc;
|
||||
static char **appArgv;
|
||||
|
||||
|
||||
static JvmlLauncherData* initJvmlLauncherData(void) {
|
||||
char* launcherLibPath = 0;
|
||||
void* jvmLauncherLibHandle = 0;
|
||||
JvmlLauncherAPI_GetAPIFunc getApi = 0;
|
||||
JvmlLauncherAPI_CreateFunType createJvmlLauncher = 0;
|
||||
JvmlLauncherAPI* api = 0;
|
||||
JvmlLauncherHandle jvmLauncherHandle = 0;
|
||||
JvmlLauncherData* result = 0;
|
||||
|
||||
launcherLibPath = getJvmLauncherLibPath();
|
||||
if (!launcherLibPath) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
jvmLauncherLibHandle = dlopen(launcherLibPath, RTLD_NOW | RTLD_LOCAL);
|
||||
if (!jvmLauncherLibHandle) {
|
||||
JP_LOG_ERRMSG(dlerror());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
getApi = dlsym(jvmLauncherLibHandle, "jvmLauncherGetAPI");
|
||||
if (!getApi) {
|
||||
JP_LOG_ERRMSG(dlerror());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
api = (*getApi)();
|
||||
if (!api) {
|
||||
JP_LOG_ERRMSG("Failed to get JvmlLauncherAPI instance");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
createJvmlLauncher = dlsym(jvmLauncherLibHandle, "jvmLauncherCreate");
|
||||
if (!createJvmlLauncher) {
|
||||
JP_LOG_ERRMSG(dlerror());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
jvmLauncherHandle = (*createJvmlLauncher)(appArgc, appArgv);
|
||||
if (!jvmLauncherHandle) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
result = jvmLauncherCreateJvmlLauncherData(api, jvmLauncherHandle);
|
||||
/* Handle released in jvmLauncherCreateJvmlLauncherData() */
|
||||
jvmLauncherHandle = 0;
|
||||
|
||||
cleanup:
|
||||
if (jvmLauncherHandle) {
|
||||
jvmLauncherCloseHandle(api, jvmLauncherHandle);
|
||||
}
|
||||
if (jvmLauncherLibHandle) {
|
||||
dlclose(jvmLauncherLibHandle);
|
||||
}
|
||||
free(launcherLibPath);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int launchJvm(JvmlLauncherData* cfg) {
|
||||
void* jliLibHandle = 0;
|
||||
void* JLI_Launch;
|
||||
int exitCode = STATUS_FAILURE;
|
||||
|
||||
jliLibHandle = dlopen(cfg->jliLibPath, RTLD_NOW | RTLD_LOCAL);
|
||||
if (!jliLibHandle) {
|
||||
JP_LOG_ERRMSG(dlerror());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
JLI_Launch = dlsym(jliLibHandle, "JLI_Launch");
|
||||
if (!JLI_Launch) {
|
||||
JP_LOG_ERRMSG(dlerror());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
exitCode = jvmLauncherStartJvm(cfg, JLI_Launch);
|
||||
|
||||
cleanup:
|
||||
if (jliLibHandle) {
|
||||
dlclose(jliLibHandle);
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int exitCode = STATUS_FAILURE;
|
||||
JvmlLauncherData* jvmLauncherData;
|
||||
|
||||
appArgc = argc;
|
||||
appArgv = argv;
|
||||
|
||||
jvmLauncherData = initJvmlLauncherData();
|
||||
if (jvmLauncherData) {
|
||||
exitCode = launchJvm(jvmLauncherData);
|
||||
free(jvmLauncherData);
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
336
src/jdk.jpackage/linux/native/applauncher/LinuxPackage.c
Normal file
336
src/jdk.jpackage/linux/native/applauncher/LinuxPackage.c
Normal file
@ -0,0 +1,336 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <linux/limits.h>
|
||||
#include <unistd.h>
|
||||
#include <libgen.h>
|
||||
#include "JvmLauncher.h"
|
||||
#include "LinuxPackage.h"
|
||||
|
||||
|
||||
static char* getModulePath(void) {
|
||||
char modulePath[PATH_MAX] = { 0 };
|
||||
ssize_t modulePathLen = 0;
|
||||
char* result = 0;
|
||||
|
||||
modulePathLen = readlink("/proc/self/exe", modulePath,
|
||||
sizeof(modulePath) - 1);
|
||||
if (modulePathLen < 0) {
|
||||
JP_LOG_ERRNO;
|
||||
return 0;
|
||||
}
|
||||
modulePath[modulePathLen] = '\0';
|
||||
result = strdup(modulePath);
|
||||
if (!result) {
|
||||
JP_LOG_ERRNO;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
# define PACKAGE_TYPE_UNKNOWN 0
|
||||
# define PACKAGE_TYPE_RPM 1
|
||||
# define PACKAGE_TYPE_DEB 2
|
||||
|
||||
typedef struct {
|
||||
char* name;
|
||||
int type;
|
||||
} PackageDesc;
|
||||
|
||||
|
||||
static void freePackageDesc(PackageDesc* desc) {
|
||||
if (desc) {
|
||||
free(desc->name);
|
||||
free(desc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static PackageDesc* createPackageDesc(void) {
|
||||
PackageDesc* result = 0;
|
||||
|
||||
result = malloc(sizeof(PackageDesc));
|
||||
if (!result) {
|
||||
JP_LOG_ERRNO;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
result->type = PACKAGE_TYPE_UNKNOWN;
|
||||
result->name = 0;
|
||||
|
||||
cleanup:
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static PackageDesc* initPackageDesc(PackageDesc* desc, const char* str,
|
||||
int type) {
|
||||
char *newStr = strdup(str);
|
||||
if (!newStr) {
|
||||
JP_LOG_ERRNO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(desc->name);
|
||||
desc->name = newStr;
|
||||
desc->type = type;
|
||||
return desc;
|
||||
}
|
||||
|
||||
|
||||
#define POPEN_CALLBACK_USE 1
|
||||
#define POPEN_CALLBACK_IGNORE 0
|
||||
|
||||
typedef int (*popenCallbackType)(void*, const char*);
|
||||
|
||||
static int popenCommand(const char* cmdlineFormat, const char* arg,
|
||||
popenCallbackType callback, void* callbackData) {
|
||||
char* cmdline = 0;
|
||||
FILE *stream = 0;
|
||||
const size_t cmdlineLenth = strlen(cmdlineFormat) + strlen(arg);
|
||||
char* strBufBegin = 0;
|
||||
char* strBufEnd = 0;
|
||||
char* strBufNextChar = 0;
|
||||
char* strNewBufBegin = 0;
|
||||
size_t strBufCapacity = 0;
|
||||
int callbackMode = POPEN_CALLBACK_USE;
|
||||
int exitCode = -1;
|
||||
int c;
|
||||
|
||||
cmdline = malloc(cmdlineLenth + 1 /* \0 */);
|
||||
if (!cmdline) {
|
||||
JP_LOG_ERRNO;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 5
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
|
||||
#endif
|
||||
if (0 > snprintf(cmdline, cmdlineLenth, cmdlineFormat, arg)) {
|
||||
JP_LOG_ERRNO;
|
||||
goto cleanup;
|
||||
}
|
||||
#if defined(__GNUC__) && __GNUC__ >= 5
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
JP_LOG_TRACE("popen: (%s)", cmdline);
|
||||
|
||||
stream = popen(cmdline, "r");
|
||||
if (!stream) {
|
||||
JP_LOG_ERRNO;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
c = fgetc(stream);
|
||||
if((EOF == c || '\n' == c)) {
|
||||
if (POPEN_CALLBACK_USE == callbackMode
|
||||
&& strBufBegin != strBufNextChar) {
|
||||
*strBufNextChar = 0;
|
||||
JP_LOG_TRACE("popen: [%s]", strBufBegin);
|
||||
callbackMode = (*callback)(callbackData, strBufBegin);
|
||||
strBufNextChar = strBufBegin;
|
||||
}
|
||||
|
||||
if (EOF == c) {
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strBufNextChar == strBufEnd) {
|
||||
/* Double buffer size */
|
||||
strBufCapacity = strBufCapacity * 2 + 1;
|
||||
strNewBufBegin = realloc(strBufBegin, strBufCapacity);
|
||||
if (!strNewBufBegin) {
|
||||
JP_LOG_ERRNO;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
strBufNextChar = strNewBufBegin + (strBufNextChar - strBufBegin);
|
||||
strBufEnd = strNewBufBegin + strBufCapacity;
|
||||
strBufBegin = strNewBufBegin;
|
||||
}
|
||||
|
||||
*strBufNextChar++ = (char)c;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (stream) {
|
||||
exitCode = pclose(stream);
|
||||
}
|
||||
|
||||
if (strBufBegin) {
|
||||
free(strBufBegin);
|
||||
}
|
||||
|
||||
free(cmdline);
|
||||
|
||||
JP_LOG_TRACE("popen: exit: %d", exitCode);
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
|
||||
static char* concat(const char *x, const char *y) {
|
||||
const size_t lenX = strlen(x);
|
||||
const size_t lenY = strlen(y);
|
||||
|
||||
char *result = malloc(lenX + lenY + 1 /* \0 */);
|
||||
if (!result) {
|
||||
JP_LOG_ERRNO;
|
||||
} else {
|
||||
strcpy(result, x);
|
||||
strcat(result, y);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int initRpmPackage(void* desc, const char* str) {
|
||||
initPackageDesc((PackageDesc*)desc, str, PACKAGE_TYPE_RPM);
|
||||
return POPEN_CALLBACK_IGNORE;
|
||||
}
|
||||
|
||||
|
||||
static int initDebPackage(void* desc, const char* str) {
|
||||
char* colonChrPos = strchr(str, ':');
|
||||
if (colonChrPos) {
|
||||
*colonChrPos = 0;
|
||||
}
|
||||
initPackageDesc((PackageDesc*)desc, str, PACKAGE_TYPE_DEB);
|
||||
return POPEN_CALLBACK_IGNORE;
|
||||
}
|
||||
|
||||
|
||||
#define LAUNCHER_LIB_NAME "/libapplauncher.so"
|
||||
|
||||
static int findLauncherLib(void* launcherLibPath, const char* str) {
|
||||
char* buf = 0;
|
||||
const size_t strLen = strlen(str);
|
||||
const size_t launcherLibNameLen = strlen(LAUNCHER_LIB_NAME);
|
||||
|
||||
if (launcherLibNameLen <= strLen
|
||||
&& !strcmp(str + strLen - launcherLibNameLen, LAUNCHER_LIB_NAME)) {
|
||||
buf = strdup(str);
|
||||
if (!buf) {
|
||||
JP_LOG_ERRNO;
|
||||
} else {
|
||||
*(char**)launcherLibPath = buf;
|
||||
}
|
||||
return POPEN_CALLBACK_IGNORE;
|
||||
}
|
||||
return POPEN_CALLBACK_USE;
|
||||
}
|
||||
|
||||
|
||||
static PackageDesc* findOwnerOfFile(const char* path) {
|
||||
int popenStatus = -1;
|
||||
PackageDesc* pkg = 0;
|
||||
|
||||
pkg = createPackageDesc();
|
||||
if (!pkg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
popenStatus = popenCommand(
|
||||
"rpm --queryformat '%{NAME}' -qf '%s' 2>/dev/null", path,
|
||||
initRpmPackage, pkg);
|
||||
if (popenStatus) {
|
||||
pkg->type = PACKAGE_TYPE_UNKNOWN;
|
||||
popenStatus = popenCommand("dpkg -S '%s' 2>/dev/null", path,
|
||||
initDebPackage, pkg);
|
||||
}
|
||||
|
||||
if (popenStatus) {
|
||||
pkg->type = PACKAGE_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
if (PACKAGE_TYPE_UNKNOWN == pkg->type || !pkg->name) {
|
||||
freePackageDesc(pkg);
|
||||
pkg = 0;
|
||||
}
|
||||
|
||||
if (pkg) {
|
||||
JP_LOG_TRACE("owner pkg: (%s|%d)", pkg->name, pkg->type);
|
||||
}
|
||||
|
||||
return pkg;
|
||||
}
|
||||
|
||||
|
||||
char* getJvmLauncherLibPath(void) {
|
||||
char* modulePath = 0;
|
||||
char* appImageDir = 0;
|
||||
char* launcherLibPath = 0;
|
||||
const char* pkgQueryCmd = 0;
|
||||
int popenStatus = -1;
|
||||
PackageDesc* pkg = 0;
|
||||
|
||||
modulePath = getModulePath();
|
||||
if (!modulePath) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
pkg = findOwnerOfFile(modulePath);
|
||||
if (!pkg) {
|
||||
/* Not a package install */
|
||||
/* Launcher should be in "bin" subdirectory of app image. */
|
||||
/* Launcher lib should be in "lib" subdirectory of app image. */
|
||||
appImageDir = dirname(dirname(modulePath));
|
||||
launcherLibPath = concat(appImageDir, "/lib" LAUNCHER_LIB_NAME);
|
||||
} else {
|
||||
if (PACKAGE_TYPE_RPM == pkg->type) {
|
||||
pkgQueryCmd = "rpm -ql '%s' 2>/dev/null";
|
||||
} else if (PACKAGE_TYPE_RPM == pkg->type) {
|
||||
pkgQueryCmd = "dpkg -L '%s' 2>/dev/null";
|
||||
} else {
|
||||
/* Should never happen */
|
||||
JP_LOG_ERRMSG("Internal error");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
popenStatus = popenCommand(pkgQueryCmd, pkg->name, findLauncherLib,
|
||||
&launcherLibPath);
|
||||
if (popenStatus) {
|
||||
free(launcherLibPath);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
free(modulePath);
|
||||
freePackageDesc(pkg);
|
||||
|
||||
return launcherLibPath;
|
||||
}
|
39
src/jdk.jpackage/linux/native/applauncher/LinuxPackage.h
Normal file
39
src/jdk.jpackage/linux/native/applauncher/LinuxPackage.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef LinuxPackage_h
|
||||
#define LinuxPackage_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
char* getJvmLauncherLibPath(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef LinuxPackage_h */
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,8 +23,10 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "kludge_c++11.h"
|
||||
|
||||
#include <memory>
|
||||
#include "JvmLauncher.h"
|
||||
#include "AppLauncher.h"
|
||||
#include "FileUtils.h"
|
||||
#include "UnixSysInfo.h"
|
||||
@ -44,6 +46,8 @@ size_t hash(const std::string& str) {
|
||||
return h;
|
||||
}
|
||||
|
||||
Jvm* jvmLauncher;
|
||||
|
||||
void launchApp() {
|
||||
const tstring launcherPath = SysInfo::getProcessModulePath();
|
||||
|
||||
@ -116,14 +120,38 @@ void launchApp() {
|
||||
}
|
||||
JP_CATCH_ALL;
|
||||
|
||||
appLauncher.launch();
|
||||
jvmLauncher = appLauncher.createJvmLauncher();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
extern "C" {
|
||||
|
||||
JNIEXPORT JvmlLauncherHandle jvmLauncherCreate(int argc, char *argv[]) {
|
||||
SysInfo::argc = argc;
|
||||
SysInfo::argv = argv;
|
||||
return app::launch(std::nothrow, launchApp);
|
||||
jvmLauncher = 0;
|
||||
app::launch(std::nothrow, launchApp);
|
||||
|
||||
JvmlLauncherHandle jlh = 0;
|
||||
if (jvmLauncher) {
|
||||
jlh = jvmLauncher->exportLauncher();
|
||||
const std::unique_ptr<Jvm> deleter(jvmLauncher);
|
||||
}
|
||||
|
||||
return jlh;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void dcon() __attribute__((destructor));
|
||||
|
||||
void dcon() {
|
||||
LOG_TRACE("unload");
|
||||
}
|
||||
|
||||
} // namespace
|
@ -62,6 +62,11 @@ public final class ApplicationLayout implements PathGroup.Facade<ApplicationLayo
|
||||
* Directory with application Java modules.
|
||||
*/
|
||||
MODULES,
|
||||
|
||||
/**
|
||||
* Linux app launcher shared library.
|
||||
*/
|
||||
LINUX_APPLAUNCHER_LIB
|
||||
}
|
||||
|
||||
ApplicationLayout(Map<Object, Path> paths) {
|
||||
@ -131,7 +136,8 @@ public final class ApplicationLayout implements PathGroup.Facade<ApplicationLayo
|
||||
PathRole.RUNTIME, Path.of("lib/runtime"),
|
||||
PathRole.RUNTIME_HOME, Path.of("lib/runtime"),
|
||||
PathRole.DESKTOP, Path.of("lib"),
|
||||
PathRole.MODULES, Path.of("lib/app/mods")
|
||||
PathRole.MODULES, Path.of("lib/app/mods"),
|
||||
PathRole.LINUX_APPLAUNCHER_LIB, Path.of("lib/libapplauncher.so")
|
||||
));
|
||||
}
|
||||
|
||||
@ -186,7 +192,9 @@ public final class ApplicationLayout implements PathGroup.Facade<ApplicationLayo
|
||||
PathRole.RUNTIME, lib.resolve("runtime"),
|
||||
PathRole.RUNTIME_HOME, lib.resolve("runtime"),
|
||||
PathRole.DESKTOP, lib,
|
||||
PathRole.MODULES, lib.resolve("app/mods")
|
||||
PathRole.MODULES, lib.resolve("app/mods"),
|
||||
PathRole.LINUX_APPLAUNCHER_LIB, lib.resolve(
|
||||
"lib/libapplauncher.so")
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <jni.h>
|
||||
#include "tstrings.h"
|
||||
#include "JvmLauncher.h"
|
||||
#include "Log.h"
|
||||
#include "Dll.h"
|
||||
@ -39,6 +39,16 @@
|
||||
#define LAUNCH_FUNC "JLI_Launch"
|
||||
#endif
|
||||
|
||||
Jvm::Jvm() {
|
||||
LOG_TRACE(tstrings::any() << "Jvm(" << this << ")::Jvm()");
|
||||
}
|
||||
|
||||
|
||||
Jvm::~Jvm() {
|
||||
LOG_TRACE(tstrings::any() << "Jvm(" << this << ")::~Jvm()");
|
||||
}
|
||||
|
||||
|
||||
Jvm& Jvm::initFromConfigFile(const CfgFile& cfgFile) {
|
||||
const CfgFile::Properties& appOptions = cfgFile.getProperties(
|
||||
SectionName::Application);
|
||||
@ -160,69 +170,191 @@ bool Jvm::isWithSplash() const {
|
||||
|
||||
|
||||
namespace {
|
||||
void convertArgs(const std::vector<std::string>& args, std::vector<char*>& argv) {
|
||||
argv.reserve(args.size() + 1);
|
||||
argv.resize(0);
|
||||
|
||||
std::vector<std::string>::const_iterator it = args.begin();
|
||||
const std::vector<std::string>::const_iterator end = args.end();
|
||||
struct JvmlLauncherHandleCloser {
|
||||
typedef JvmlLauncherHandle pointer;
|
||||
|
||||
for (; it != end; ++it) {
|
||||
argv.push_back(const_cast<char*>(it->c_str()));
|
||||
};
|
||||
void operator()(JvmlLauncherHandle h) {
|
||||
jvmLauncherCloseHandle(jvmLauncherGetAPI(), h);
|
||||
}
|
||||
};
|
||||
|
||||
struct JvmlLauncherDataDeleter {
|
||||
typedef JvmlLauncherData* pointer;
|
||||
|
||||
void operator()(JvmlLauncherData* ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
// Add treminal '0'.
|
||||
argv.push_back(0);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void Jvm::launch() {
|
||||
typedef int (JNICALL *LaunchFuncType)(int argc, char ** argv,
|
||||
int jargc, const char** jargv,
|
||||
int appclassc, const char** appclassv,
|
||||
const char* fullversion,
|
||||
const char* dotversion,
|
||||
const char* pname,
|
||||
const char* lname,
|
||||
jboolean javaargs,
|
||||
jboolean cpwildcard,
|
||||
jboolean javaw,
|
||||
jint ergo);
|
||||
typedef std::unique_ptr<
|
||||
JvmlLauncherHandle, JvmlLauncherHandleCloser> AutoJvmlLauncherHandle;
|
||||
|
||||
std::vector<char*> argv;
|
||||
#ifdef TSTRINGS_WITH_WCHAR
|
||||
std::vector<std::string> mbcs_args;
|
||||
do {
|
||||
tstring_array::const_iterator it = args.begin();
|
||||
const tstring_array::const_iterator end = args.end();
|
||||
for (; it != end; ++it) {
|
||||
mbcs_args.push_back(tstrings::toACP(*it));
|
||||
}
|
||||
} while (0);
|
||||
convertArgs(mbcs_args, argv);
|
||||
#else
|
||||
convertArgs(args, argv);
|
||||
#endif
|
||||
typedef std::unique_ptr<
|
||||
JvmlLauncherData, JvmlLauncherDataDeleter> AutoJvmlLauncherData;
|
||||
|
||||
// Don't count terminal '0'.
|
||||
const int argc = (int)argv.size() - 1;
|
||||
AutoJvmlLauncherHandle jlh(exportLauncher());
|
||||
|
||||
JvmlLauncherAPI* api = jvmLauncherGetAPI();
|
||||
|
||||
AutoJvmlLauncherData jld(jvmLauncherCreateJvmlLauncherData(api,
|
||||
jlh.release()));
|
||||
|
||||
LOG_TRACE(tstrings::any() << "JVM library: \"" << jvmPath << "\"");
|
||||
|
||||
DllFunction<LaunchFuncType> func(Dll(jvmPath), LAUNCH_FUNC);
|
||||
int exitStatus = func(argc, argv.data(),
|
||||
0, 0,
|
||||
0, 0,
|
||||
"",
|
||||
"",
|
||||
"java",
|
||||
"java",
|
||||
JNI_FALSE,
|
||||
JNI_FALSE,
|
||||
JNI_FALSE,
|
||||
0);
|
||||
DllFunction<void*> func(Dll(jvmPath), LAUNCH_FUNC);
|
||||
|
||||
int exitStatus = jvmLauncherStartJvm(jld.get(), func.operator void*());
|
||||
|
||||
if (exitStatus != 0) {
|
||||
JP_THROW("Failed to launch JVM");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
struct JliLaunchData {
|
||||
std::string jliLibPath;
|
||||
std::vector<std::string> args;
|
||||
|
||||
int initJvmlLauncherData(JvmlLauncherData* ptr, int bufferSize) const {
|
||||
int minimalBufferSize = initJvmlLauncherData(0);
|
||||
if (minimalBufferSize <= bufferSize) {
|
||||
initJvmlLauncherData(ptr);
|
||||
}
|
||||
return minimalBufferSize;
|
||||
}
|
||||
|
||||
private:
|
||||
int initJvmlLauncherData(JvmlLauncherData* ptr) const {
|
||||
// Store path to JLI library just behind JvmlLauncherData header.
|
||||
char* curPtr = reinterpret_cast<char*>(ptr + 1);
|
||||
do {
|
||||
const size_t count = sizeof(char)
|
||||
* (jliLibPath.size() + 1 /* trailing zero */);
|
||||
if (ptr) {
|
||||
std::memcpy(curPtr, jliLibPath.c_str(), count);
|
||||
ptr->jliLibPath = curPtr;
|
||||
}
|
||||
curPtr += count;
|
||||
} while (false);
|
||||
|
||||
// Next write array of char* pointing to JLI lib arg strings.
|
||||
if (ptr) {
|
||||
ptr->jliLaunchArgv = reinterpret_cast<char**>(curPtr);
|
||||
ptr->jliLaunchArgc = (int)args.size();
|
||||
// Add terminal '0' arg.
|
||||
ptr->jliLaunchArgv[ptr->jliLaunchArgc] = 0;
|
||||
}
|
||||
|
||||
// Skip memory occupied by char* array.
|
||||
curPtr += sizeof(char*) * (args.size() + 1 /* terminal '0' arg */);
|
||||
|
||||
// Store array of strings.
|
||||
for (size_t i = 0; i != args.size(); i++) {
|
||||
const size_t count = (args[i].size() + 1 /* trailing zero */);
|
||||
if (ptr) {
|
||||
std::memcpy(curPtr, args[i].c_str(), count);
|
||||
ptr->jliLaunchArgv[i] = curPtr;
|
||||
}
|
||||
curPtr += count;
|
||||
};
|
||||
|
||||
const size_t bufferSize = curPtr - reinterpret_cast<char*>(ptr);
|
||||
if (ptr) {
|
||||
LOG_TRACE(tstrings::any() << "Initialized " << bufferSize
|
||||
<< " bytes at " << ptr << " address");
|
||||
} else {
|
||||
LOG_TRACE(tstrings::any() << "Need " << bufferSize
|
||||
<< " bytes for JvmlLauncherData buffer");
|
||||
}
|
||||
return static_cast<int>(bufferSize);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
JvmlLauncherHandle Jvm::exportLauncher() const {
|
||||
std::unique_ptr<JliLaunchData> result(new JliLaunchData());
|
||||
|
||||
result->jliLibPath = tstrings::toUtf8(jvmPath);
|
||||
|
||||
#ifdef TSTRINGS_WITH_WCHAR
|
||||
do {
|
||||
tstring_array::const_iterator it = args.begin();
|
||||
const tstring_array::const_iterator end = args.end();
|
||||
for (; it != end; ++it) {
|
||||
result->args.push_back(tstrings::toACP(*it));
|
||||
}
|
||||
} while (0);
|
||||
#else
|
||||
result->args = args;
|
||||
#endif
|
||||
|
||||
return result.release();
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void closeHandle(JvmlLauncherHandle h) {
|
||||
JP_TRY;
|
||||
|
||||
JliLaunchData* data = static_cast<JliLaunchData*>(h);
|
||||
const std::unique_ptr<JliLaunchData> deleter(data);
|
||||
|
||||
JP_CATCH_ALL;
|
||||
}
|
||||
|
||||
|
||||
int getJvmlLauncherDataSize(JvmlLauncherHandle h) {
|
||||
JP_TRY;
|
||||
|
||||
const JliLaunchData* data = static_cast<const JliLaunchData*>(h);
|
||||
return data->initJvmlLauncherData(0, 0);
|
||||
|
||||
JP_CATCH_ALL;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
JvmlLauncherData* initJvmlLauncherData(JvmlLauncherHandle h,
|
||||
void* ptr, int bufferSize) {
|
||||
JP_TRY;
|
||||
|
||||
const JliLaunchData* data = static_cast<const JliLaunchData*>(h);
|
||||
const int usedBufferSize = data->initJvmlLauncherData(
|
||||
static_cast<JvmlLauncherData*>(ptr), bufferSize);
|
||||
if (bufferSize <= usedBufferSize) {
|
||||
return static_cast<JvmlLauncherData*>(ptr);
|
||||
}
|
||||
|
||||
JP_CATCH_ALL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
class Impl : public JvmlLauncherAPI {
|
||||
public:
|
||||
Impl() {
|
||||
this->closeHandle = ::closeHandle;
|
||||
this->getJvmlLauncherDataSize = ::getJvmlLauncherDataSize;
|
||||
this->initJvmlLauncherData = ::initJvmlLauncherData;
|
||||
}
|
||||
} api;
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
JNIEXPORT JvmlLauncherAPI* jvmLauncherGetAPI(void) {
|
||||
return &api;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
@ -27,6 +27,67 @@
|
||||
#ifndef JvmLauncher_h
|
||||
#define JvmLauncher_h
|
||||
|
||||
|
||||
#include "jni.h" /* JNIEXPORT */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
const char* jliLibPath;
|
||||
int jliLaunchArgc;
|
||||
char** jliLaunchArgv;
|
||||
} JvmlLauncherData;
|
||||
|
||||
typedef void* JvmlLauncherHandle;
|
||||
|
||||
typedef void (*JvmlLauncherAPI_CloseHandleFunc)(JvmlLauncherHandle);
|
||||
typedef int (*JvmlLauncherAPI_GetJvmlLauncherDataSizeFunc)(JvmlLauncherHandle);
|
||||
typedef JvmlLauncherData* (*JvmlLauncherAPI_InitJvmlLauncherDataFunc)(JvmlLauncherHandle, void*, int);
|
||||
|
||||
typedef struct {
|
||||
JvmlLauncherAPI_CloseHandleFunc closeHandle;
|
||||
JvmlLauncherAPI_GetJvmlLauncherDataSizeFunc getJvmlLauncherDataSize;
|
||||
JvmlLauncherAPI_InitJvmlLauncherDataFunc initJvmlLauncherData;
|
||||
} JvmlLauncherAPI;
|
||||
|
||||
typedef JvmlLauncherAPI* (*JvmlLauncherAPI_GetAPIFunc)(void);
|
||||
|
||||
JNIEXPORT JvmlLauncherAPI* jvmLauncherGetAPI(void);
|
||||
|
||||
static inline void jvmLauncherCloseHandle(JvmlLauncherAPI* api, JvmlLauncherHandle h) {
|
||||
(*api->closeHandle)(h);
|
||||
}
|
||||
|
||||
static inline int jvmLauncherGetJvmlLauncherDataSize(JvmlLauncherAPI* api,
|
||||
JvmlLauncherHandle h) {
|
||||
return (*api->getJvmlLauncherDataSize)(h);
|
||||
}
|
||||
|
||||
static inline JvmlLauncherData* jvmLauncherInitJvmlLauncherData(JvmlLauncherAPI* api,
|
||||
JvmlLauncherHandle h, void* ptr, int bufferSize) {
|
||||
return (*api->initJvmlLauncherData)(h, ptr, bufferSize);
|
||||
}
|
||||
|
||||
JvmlLauncherData* jvmLauncherCreateJvmlLauncherData(JvmlLauncherAPI* api, JvmlLauncherHandle h);
|
||||
int jvmLauncherStartJvm(JvmlLauncherData* jvmArgs, void* JLI_Launch);
|
||||
|
||||
void jvmLauncherLog(const char* format, ...);
|
||||
|
||||
#define JP_LOG_ERRMSG(msg) do { jvmLauncherLog((msg)); } while (0)
|
||||
#define JP_LOG_ERRNO JP_LOG_ERRMSG(strerror(errno))
|
||||
#define JP_LOG_TRACE jvmLauncherLog
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "tstrings.h"
|
||||
|
||||
class CfgFile;
|
||||
@ -34,6 +95,9 @@ class CfgFile;
|
||||
|
||||
class Jvm {
|
||||
public:
|
||||
Jvm();
|
||||
~Jvm();
|
||||
|
||||
Jvm& initFromConfigFile(const CfgFile& cfgFile);
|
||||
|
||||
Jvm& addArgument(const tstring& value) {
|
||||
@ -54,9 +118,13 @@ public:
|
||||
|
||||
void launch();
|
||||
|
||||
JvmlLauncherHandle exportLauncher() const;
|
||||
|
||||
private:
|
||||
tstring jvmPath;
|
||||
tstring_array args;
|
||||
};
|
||||
|
||||
#endif // #ifdef __cplusplus
|
||||
|
||||
#endif // JvmLauncher_h
|
||||
|
132
src/jdk.jpackage/share/native/applauncher/JvmLauncherLib.c
Normal file
132
src/jdk.jpackage/share/native/applauncher/JvmLauncherLib.c
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "JvmLauncher.h"
|
||||
|
||||
|
||||
typedef int (JNICALL *JLI_LaunchFuncType)(int argc, char ** argv,
|
||||
int jargc, const char** jargv,
|
||||
int appclassc, const char** appclassv,
|
||||
const char* fullversion,
|
||||
const char* dotversion,
|
||||
const char* pname,
|
||||
const char* lname,
|
||||
jboolean javaargs,
|
||||
jboolean cpwildcard,
|
||||
jboolean javaw,
|
||||
jint ergo);
|
||||
|
||||
|
||||
JvmlLauncherData* jvmLauncherCreateJvmlLauncherData(
|
||||
JvmlLauncherAPI* api, JvmlLauncherHandle h) {
|
||||
JvmlLauncherData* result = 0;
|
||||
void* buf = 0;
|
||||
int jvmLauncherDataBufferSize;
|
||||
|
||||
if (!h) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
jvmLauncherDataBufferSize = jvmLauncherGetJvmlLauncherDataSize(api, h);
|
||||
if (jvmLauncherDataBufferSize <= 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
buf = malloc(jvmLauncherDataBufferSize);
|
||||
if (!buf) {
|
||||
JP_LOG_ERRNO;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
result = jvmLauncherInitJvmlLauncherData(api, h, buf,
|
||||
jvmLauncherDataBufferSize);
|
||||
if (result) {
|
||||
/* Don't free the buffer in clean up. */
|
||||
buf = 0;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
jvmLauncherCloseHandle(api, h);
|
||||
free(buf);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static void dumpJvmlLauncherData(const JvmlLauncherData* jvmArgs) {
|
||||
int i = 0;
|
||||
JP_LOG_TRACE("jli lib: [%s]", jvmArgs->jliLibPath);
|
||||
for (i = 0; i < jvmArgs->jliLaunchArgc; ++i) {
|
||||
JP_LOG_TRACE("jli arg[%d]: [%s]", i, jvmArgs->jliLaunchArgv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int jvmLauncherStartJvm(JvmlLauncherData* jvmArgs, void* JLI_Launch) {
|
||||
int exitCode;
|
||||
|
||||
dumpJvmlLauncherData(jvmArgs);
|
||||
exitCode = (*((JLI_LaunchFuncType)JLI_Launch))(
|
||||
jvmArgs->jliLaunchArgc, jvmArgs->jliLaunchArgv,
|
||||
0, 0,
|
||||
0, 0,
|
||||
"",
|
||||
"",
|
||||
"java",
|
||||
"java",
|
||||
JNI_FALSE,
|
||||
JNI_FALSE,
|
||||
JNI_FALSE,
|
||||
0);
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
|
||||
void jvmLauncherLog(const char* format, ...) {
|
||||
const char *withLog = getenv("JPACKAGE_DEBUG");
|
||||
if (!withLog || strcmp(withLog, "true")) {
|
||||
return;
|
||||
}
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 5
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
|
||||
#endif
|
||||
vfprintf(stderr, format, args);
|
||||
fprintf(stderr, "\n");
|
||||
#if defined(__GNUC__) && __GNUC__ >= 5
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
va_end (args);
|
||||
}
|
@ -23,6 +23,8 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "kludge_c++11.h"
|
||||
|
||||
#include <memory>
|
||||
#include "app.h"
|
||||
#include "Log.h"
|
||||
@ -56,6 +58,8 @@ public:
|
||||
|
||||
class ResetLastErrorMsgAtEndOfScope {
|
||||
public:
|
||||
ResetLastErrorMsgAtEndOfScope() {
|
||||
}
|
||||
~ResetLastErrorMsgAtEndOfScope() {
|
||||
JP_NO_THROW(theLastErrorMsg = 0);
|
||||
}
|
||||
|
@ -52,13 +52,13 @@ tstring unsafe_format(tstring::const_pointer format, ...) {
|
||||
#ifdef _MSC_VER
|
||||
ret = _vsntprintf_s(&*fmtout.begin(), fmtout.size(), _TRUNCATE, format, args);
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && __GNUC__ >= 5
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
|
||||
#endif
|
||||
// With g++ this compiles only with '-std=gnu++0x' option
|
||||
ret = vsnprintf(&*fmtout.begin(), fmtout.size(), format, args);
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && __GNUC__ >= 5
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user