mirror of
https://github.com/RGBCube/serenity
synced 2025-06-13 01:42:07 +00:00
Ports: Add OpenJDK port
Port of OpenJDK 17.0.2, zero VM only. More work needed to get the full hotspot VM up and running :^) Co-Authored-By: Andrew Kaster <akaster@serenityos.org>
This commit is contained in:
parent
6eb9ebec5f
commit
1f886f94bd
11 changed files with 4308 additions and 0 deletions
|
@ -0,0 +1,259 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Kaster <andrewdkaster@gmail.com>
|
||||
Date: Sun, 12 Jun 2022 23:15:17 -0600
|
||||
Subject: [PATCH] java.base: Enable java.lang.Process on serenity
|
||||
|
||||
---
|
||||
make/modules/java.base/Launcher.gmk | 2 +-
|
||||
make/modules/java.base/lib/CoreLibraries.gmk | 3 +
|
||||
.../libjava/ProcessHandleImpl_serenity.cpp | 167 ++++++++++++++++++
|
||||
.../unix/classes/java/lang/ProcessImpl.java | 7 +-
|
||||
4 files changed, 177 insertions(+), 2 deletions(-)
|
||||
create mode 100644 src/java.base/serenity/native/libjava/ProcessHandleImpl_serenity.cpp
|
||||
|
||||
diff --git a/make/modules/java.base/Launcher.gmk b/make/modules/java.base/Launcher.gmk
|
||||
index 700ddefda..78c884dae 100644
|
||||
--- a/make/modules/java.base/Launcher.gmk
|
||||
+++ b/make/modules/java.base/Launcher.gmk
|
||||
@@ -73,7 +73,7 @@ endif
|
||||
|
||||
################################################################################
|
||||
|
||||
-ifeq ($(call isTargetOs, macosx aix linux), true)
|
||||
+ifeq ($(call isTargetOs, macosx aix linux serenity), true)
|
||||
$(eval $(call SetupJdkExecutable, BUILD_JSPAWNHELPER, \
|
||||
NAME := jspawnhelper, \
|
||||
SRC := $(TOPDIR)/src/$(MODULE)/unix/native/jspawnhelper, \
|
||||
diff --git a/make/modules/java.base/lib/CoreLibraries.gmk b/make/modules/java.base/lib/CoreLibraries.gmk
|
||||
index 0a61d009f..7867a3095 100644
|
||||
--- a/make/modules/java.base/lib/CoreLibraries.gmk
|
||||
+++ b/make/modules/java.base/lib/CoreLibraries.gmk
|
||||
@@ -90,6 +90,8 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJAVA, \
|
||||
OPTIMIZATION := HIGH, \
|
||||
CFLAGS := $(CFLAGS_JDKLIB) \
|
||||
$(LIBJAVA_CFLAGS), \
|
||||
+ CXXFLAGS := $(CXXFLAGS_JDKLIB) \
|
||||
+ $(LIBJAVA_CXXFLAGS), \
|
||||
jdk_util.c_CFLAGS := $(VERSION_CFLAGS), \
|
||||
EXTRA_HEADER_DIRS := libfdlibm, \
|
||||
WARNINGS_AS_ERRORS_xlc := false, \
|
||||
@@ -102,6 +104,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJAVA, \
|
||||
LIBS_unix := -ljvm, \
|
||||
LIBS_linux := $(LIBDL), \
|
||||
LIBS_aix := $(LIBDL) $(LIBM),\
|
||||
+ LIBS_serenity := $(LIBDL) -lcore, \
|
||||
LIBS_macosx := -framework CoreFoundation \
|
||||
-framework Foundation \
|
||||
-framework SystemConfiguration, \
|
||||
diff --git a/src/java.base/serenity/native/libjava/ProcessHandleImpl_serenity.cpp b/src/java.base/serenity/native/libjava/ProcessHandleImpl_serenity.cpp
|
||||
new file mode 100644
|
||||
index 000000000..e9bb2ec4a
|
||||
--- /dev/null
|
||||
+++ b/src/java.base/serenity/native/libjava/ProcessHandleImpl_serenity.cpp
|
||||
@@ -0,0 +1,167 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2015, 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.
|
||||
+ */
|
||||
+
|
||||
+#define AK_DONT_REPLACE_STD
|
||||
+
|
||||
+#include "jvm.h"
|
||||
+#include "jni.h"
|
||||
+#include "jni_util.h"
|
||||
+#include "java_lang_String.h"
|
||||
+
|
||||
+extern "C" {
|
||||
+#include "ProcessHandleImpl_unix.h"
|
||||
+}
|
||||
+
|
||||
+#include <AK/JsonArray.h>
|
||||
+#include <LibCore/ProcessStatisticsReader.h>
|
||||
+#include <LibCore/Stream.h>
|
||||
+#include <stdio.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+/*
|
||||
+ * Implementation of native ProcessHandleImpl functions for SERENITY.
|
||||
+ * See ProcessHandleImpl_unix.c for more details.
|
||||
+ */
|
||||
+
|
||||
+#define JAVA_TRY(expression, message) \
|
||||
+ ({ \
|
||||
+ auto _temporary_result = (expression); \
|
||||
+ if (_temporary_result.is_error()) [[unlikely]] \
|
||||
+ return throwSerenityError(env, _temporary_result.release_error(), (message)); \
|
||||
+ _temporary_result.release_value(); \
|
||||
+ })
|
||||
+
|
||||
+
|
||||
+static RefPtr<Core::File> proc_all;
|
||||
+
|
||||
+extern "C" {
|
||||
+void os_initNative(JNIEnv *env, jclass clazz) {
|
||||
+ proc_all = MUST(Core::File::open("/proc/all", Core::OpenMode::ReadOnly));
|
||||
+}
|
||||
+
|
||||
+jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
|
||||
+ jlongArray jparentArray, jlongArray jstimesArray) {
|
||||
+ return unix_getChildren(env, jpid, jarray, jparentArray, jstimesArray);
|
||||
+}
|
||||
+
|
||||
+pid_t os_getParentPidAndTimings(JNIEnv *env, pid_t pid, jlong *total, jlong *start) {
|
||||
+ auto maybe_stats = Core::ProcessStatisticsReader::get_all(proc_all);
|
||||
+ if (!maybe_stats.has_value()) {
|
||||
+ JNU_ThrowByNameWithLastError(env,
|
||||
+ "java/lang/RuntimeException", "ProcessStatisticsReader::get_all failed");
|
||||
+ return -1;
|
||||
+ }
|
||||
+ auto stats = maybe_stats.release_value();
|
||||
+ auto proc_it = find_if(stats.processes.begin(), stats.processes.end(), [pid](auto& proc_stats) {
|
||||
+ return proc_stats.pid == pid;
|
||||
+ });
|
||||
+ if (proc_it == stats.processes.end()) {
|
||||
+ JNU_ThrowByNameWithLastError(env,
|
||||
+ "java/lang/RuntimeException", "Selected pid does not exist");
|
||||
+ return -1;
|
||||
+ }
|
||||
+ auto& proc = *proc_it;
|
||||
+
|
||||
+ for (auto& thread : proc.threads) {
|
||||
+ *total += thread.time_user + thread.time_kernel;
|
||||
+ }
|
||||
+
|
||||
+ *start = 0; // FIXME: When did thread start? not reported in /proc/all
|
||||
+
|
||||
+ return proc.ppid;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void throwSerenityError(JNIEnv* env, Error const& e, StringView msg) {
|
||||
+ char err_buf[256];
|
||||
+ if (e.is_errno())
|
||||
+ getErrorString(e.code(), err_buf, sizeof(err_buf));
|
||||
+ else
|
||||
+ strncpy(err_buf, e.string_literal().characters_without_null_termination(), sizeof(err_buf) - 1);
|
||||
+ jstring s = JNU_NewStringPlatform(env, err_buf);
|
||||
+ if (s != NULL) {
|
||||
+ jobject x = JNU_NewObjectByName(env, "java/lang/RuntimeException",
|
||||
+ "(Ljava/lang/String;)V", s);
|
||||
+ if (x != NULL) {
|
||||
+ env->Throw((jthrowable)x);
|
||||
+ }
|
||||
+ }
|
||||
+ if (!env->ExceptionOccurred()) {
|
||||
+ JNU_ThrowByName(env, "java/lang/RuntimeException", msg.characters_without_null_termination());
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void os_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
|
||||
+ auto maybe_stats = Core::ProcessStatisticsReader::get_all(proc_all);
|
||||
+ if (!maybe_stats.has_value()) {
|
||||
+ JNU_ThrowByNameWithLastError(env,
|
||||
+ "java/lang/RuntimeException", "ProcessStatisticsReader::get_all failed");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ auto stats = maybe_stats.release_value();
|
||||
+ auto proc_it = find_if(stats.processes.begin(), stats.processes.end(), [pid](auto& proc_stats) {
|
||||
+ return proc_stats.pid == pid;
|
||||
+ });
|
||||
+ if (proc_it == stats.processes.end()) {
|
||||
+ JNU_ThrowByNameWithLastError(env,
|
||||
+ "java/lang/RuntimeException", "Selected pid does not exist");
|
||||
+ return;
|
||||
+ }
|
||||
+ auto& proc = *proc_it;
|
||||
+
|
||||
+ unix_getUserInfo(env, jinfo, proc.pid);
|
||||
+ JNU_CHECK_EXCEPTION(env);
|
||||
+
|
||||
+ char cmdline_name[256];
|
||||
+ snprintf(cmdline_name , sizeof(cmdline_name) - 1, "/proc/%d/cmdline", pid);
|
||||
+
|
||||
+ auto cmdline_file = JAVA_TRY(Core::Stream::File::open(cmdline_name, Core::Stream::OpenMode::Read), "Unable to open /proc/pid/cmdline"sv);
|
||||
+ auto contents = JAVA_TRY(cmdline_file->read_all(), "Unable to read /proc/pid/cmdline"sv);
|
||||
+ auto cmdline = JAVA_TRY(JsonValue::from_string(contents), "Invalid JSON in /proc/pid/cmdline"sv);
|
||||
+
|
||||
+ if (!cmdline.is_array())
|
||||
+ return throwSerenityError(env, Error::from_string_literal("Not an array"), "Unexpected JSON in /proc/pid/cmdline");
|
||||
+
|
||||
+ jstring cmdexe = JNU_NewStringPlatform(env, cmdline.as_array()[0].as_string().characters());
|
||||
+ env->ExceptionClear(); // unconditionally clear any exception
|
||||
+ env->SetObjectField(jinfo, ProcessHandleImpl_Info_commandID, cmdexe);
|
||||
+
|
||||
+ int arr_size = cmdline.as_array().size();
|
||||
+ jclass string_clazz = JNU_ClassString(env);
|
||||
+ CHECK_NULL(string_clazz);
|
||||
+ jobjectArray java_cmdline = env->NewObjectArray(arr_size, string_clazz, NULL);
|
||||
+ CHECK_NULL(java_cmdline);
|
||||
+ jstring elem = NULL;
|
||||
+ for (int i = 0; i < arr_size; ++i) {
|
||||
+ elem = JNU_NewStringPlatform(env, cmdline.as_array()[i].as_string().characters());
|
||||
+ CHECK_NULL(elem);
|
||||
+ env->SetObjectArrayElement(java_cmdline, i, elem);
|
||||
+ JNU_CHECK_EXCEPTION(env);
|
||||
+ }
|
||||
+ env->SetObjectField(jinfo, ProcessHandleImpl_Info_argumentsID, java_cmdline);
|
||||
+ JNU_CHECK_EXCEPTION(env);
|
||||
+}
|
||||
+}
|
||||
diff --git a/src/java.base/unix/classes/java/lang/ProcessImpl.java b/src/java.base/unix/classes/java/lang/ProcessImpl.java
|
||||
index 2bf36f8f1..317bbf158 100644
|
||||
--- a/src/java.base/unix/classes/java/lang/ProcessImpl.java
|
||||
+++ b/src/java.base/unix/classes/java/lang/ProcessImpl.java
|
||||
@@ -89,7 +89,9 @@ final class ProcessImpl extends Process {
|
||||
|
||||
BSD(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
|
||||
|
||||
- AIX(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK);
|
||||
+ AIX(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
|
||||
+
|
||||
+ SERENITY(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK);
|
||||
|
||||
final LaunchMechanism defaultLaunchMechanism;
|
||||
final Set<LaunchMechanism> validLaunchMechanisms;
|
||||
@@ -135,6 +137,7 @@ final class ProcessImpl extends Process {
|
||||
if (osName.equals("Linux")) { return LINUX; }
|
||||
if (osName.contains("OS X")) { return BSD; }
|
||||
if (osName.equals("AIX")) { return AIX; }
|
||||
+ if (osName.equals("SerenityOS")) { return SERENITY; }
|
||||
|
||||
throw new Error(osName + " is not a supported OS platform.");
|
||||
}
|
||||
@@ -348,6 +351,7 @@ final class ProcessImpl extends Process {
|
||||
switch (platform) {
|
||||
case LINUX:
|
||||
case BSD:
|
||||
+ case SERENITY:
|
||||
stdin = (fds[0] == -1) ?
|
||||
ProcessBuilder.NullOutputStream.INSTANCE :
|
||||
new ProcessPipeOutputStream(fds[0]);
|
||||
@@ -467,6 +471,7 @@ final class ProcessImpl extends Process {
|
||||
case LINUX:
|
||||
case BSD:
|
||||
case AIX:
|
||||
+ case SERENITY:
|
||||
// There is a risk that pid will be recycled, causing us to
|
||||
// kill the wrong process! So we only terminate processes
|
||||
// that appear to still be running. Even with this check,
|
Loading…
Add table
Add a link
Reference in a new issue