From 15a219fc080255adadc2602c7113dac064832c0a Mon Sep 17 00:00:00 2001 From: Stephanie Gawroriski Date: Mon, 18 Mar 2024 08:27:05 +0000 Subject: [PATCH] Add initial start of initialization through libjvm. --- nanocoat/assets/doc/frontend-libjvm.mkd | 29 ++++++ nanocoat/frontend/libjvm/CMakeLists.txt | 3 +- nanocoat/frontend/libjvm/revProto.c | 11 --- nanocoat/frontend/libjvm/vmInit.c | 148 ++++++++++++++++++++++++++++ nanocoat/include/frontend/libjvm/revProto.h | 3 - nanocoat/src/alloc.c | 2 + 6 files changed, 181 insertions(+), 15 deletions(-) create mode 100644 nanocoat/assets/doc/frontend-libjvm.mkd create mode 100644 nanocoat/frontend/libjvm/vmInit.c diff --git a/nanocoat/assets/doc/frontend-libjvm.mkd b/nanocoat/assets/doc/frontend-libjvm.mkd new file mode 100644 index 0000000000..93876d590e --- /dev/null +++ b/nanocoat/assets/doc/frontend-libjvm.mkd @@ -0,0 +1,29 @@ +# libjvm Frontend + +This frontend is intended to provide a drop-in replacement of the `jvm` +library commonly found on existing Java installations. The library itself +is usually launched from the `java` command. + +## Existing Programs + +Any program which pulls in `libjvm` and then creates a virtual machine may +be able to function and run. + +## Installation + +This requires making the library known, such as in the configuration +of `/etc/java-$VERSION-$VENDOR/jvm-$OS_ARCH.cfg`: + +``` +-squirreljme KNOWN +``` + +Then creating a directory within `/usr/lib/jvm/$VERSION/lib`, this for +example will be `default-java` on Debian, then within a subdirectory +of that called `squirreljme` where `libjvm.so` is to be placed. + +For a user installed JDK for example one installed from IntelliJ, as an +example the given files would be: + + * `~/.jdks/liberica-1.8.0_392/jre/lib/amd64/jvm.cfg` + * `~/.jdks/liberica-1.8.0_392/jre/lib/amd64/squirreljme/libjvm.so` diff --git a/nanocoat/frontend/libjvm/CMakeLists.txt b/nanocoat/frontend/libjvm/CMakeLists.txt index 2059db2f20..bbd6b9bc78 100644 --- a/nanocoat/frontend/libjvm/CMakeLists.txt +++ b/nanocoat/frontend/libjvm/CMakeLists.txt @@ -15,7 +15,8 @@ squirreljme_include("docker.cmake") # Define library add_library(libJvm SHARED $ - revProto.c) + revProto.c + vmInit.c) # Always make this position independent set_property(TARGET libJvm diff --git a/nanocoat/frontend/libjvm/revProto.c b/nanocoat/frontend/libjvm/revProto.c index 3b9a1483de..3ef813539a 100644 --- a/nanocoat/frontend/libjvm/revProto.c +++ b/nanocoat/frontend/libjvm/revProto.c @@ -10,23 +10,12 @@ #include "frontend/libjvm/revProto.h" #include "sjme/debug.h" -libjvm_re_int JNI_CreateJavaVM(libjvm_re_undefined8* param_1, - libjvm_re_long* param_2, libjvm_re_undefined8 param_3) -{ - sjme_todo("Impl?"); -} - libjvm_re_undefined8 JNI_GetCreatedJavaVMs(libjvm_re_undefined8* param_1, libjvm_re_int param_2, libjvm_re_undefined4* param_3) { sjme_todo("Impl?"); } -libjvm_re_int JNI_GetDefaultJavaVMInitArgs(libjvm_re_int* param_1) -{ - sjme_todo("Impl?"); -} - void JVM_Accept(libjvm_re_int param_1, libjvm_re_sockaddr* param_2, libjvm_re_socklen_t* param_3) { diff --git a/nanocoat/frontend/libjvm/vmInit.c b/nanocoat/frontend/libjvm/vmInit.c new file mode 100644 index 0000000000..14b6efcdbc --- /dev/null +++ b/nanocoat/frontend/libjvm/vmInit.c @@ -0,0 +1,148 @@ +/* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*- +// --------------------------------------------------------------------------- +// SquirrelJME +// Copyright (C) Stephanie Gawroriski +// --------------------------------------------------------------------------- +// SquirrelJME is under the Mozilla Public License Version 2.0. +// See license.mkd for licensing and copyright information. +// -------------------------------------------------------------------------*/ + +#include + +#include "sjme/alloc.h" +#include "sjme/boot.h" +#include "sjme/debug.h" + +/** Default amount of memory. */ +#define SJME_JVM_INIT_MEMORY 67108864 + +/** + * Creates a new Java Virtual Machine. + * + * @param outVm The resultant virtual machine. + * @param outEnv The output environment. + * @param vmArgs The arguments to the virtual machine creation. + * @return + */ +sjme_attrUnused jint JNICALL JNI_CreateJavaVM( + sjme_attrOutNotNull JavaVM** outVm, + sjme_attrOutNotNull void** outEnv, + sjme_attrInNotNull void* vmArgs) +{ + struct JNIInvokeInterface_* resultVm; + struct JNINativeInterface_* resultEnv; + sjme_alloc_pool* pool; + sjme_nvm_state* nvmState; + JavaVMInitArgs* args; + jint i; + + if (outVm == NULL || outEnv == NULL || vmArgs == NULL) + return JNI_EINVAL; + + /* Aliased. */ + args = vmArgs; + + /* Negative number of options?. */ + if (args->nOptions < 0) + return JNI_EINVAL; + + /* Either too old or too new. */ + if (args->version < JNI_VERSION_1_1 || args->version > JNI_VERSION_1_8) + return JNI_EVERSION; + +#if defined(SJME_CONFIG_DEBUG) + /* Debug. */ + /* OpenJDK sends these: */ + /* -Djava.class.path=. */ + /* -Dsun.java.launcher=SUN_STANDARD */ + /* -Dsun.java.launcher.pid=30954 */ + for (i = 0; i < args->nOptions; i++) + sjme_message("Arg %d: %s", i, args->options[i].optionString); +#endif + + /* Allocate the memory needed for SquirrelJME. */ + pool = NULL; + if (sjme_error_is(sjme_alloc_poolInitMalloc(&pool, + SJME_JVM_INIT_MEMORY)) || pool == NULL) + return JNI_ENOMEM; + + /* Allocate resultant function structure. */ + resultVm = NULL; + if (sjme_error_is(sjme_alloc(pool, sizeof(*resultVm), &resultVm)) || + resultVm == NULL) + goto fail_allocResultVm; + + /* Allocate environment based functions. */ + resultEnv = NULL; + if (sjme_error_is(sjme_alloc(pool, sizeof(*resultEnv), &resultEnv)) || + resultEnv == NULL) + goto fail_allocResultEnv; + + /* Boot the virtual machine. */ + nvmState = NULL; + if (sjme_error_is(sjme_nvm_boot(pool, + NULL, NULL, &nvmState)) || nvmState == NULL) + goto fail_nvmBoot; + + /* Store the environment and VM state into both structures the same. */ + resultVm->reserved0 = resultVm; + resultVm->reserved1 = resultEnv; + resultVm->reserved2 = nvmState; + resultEnv->reserved0 = resultVm; + resultEnv->reserved1 = resultEnv; + resultEnv->reserved2 = nvmState; + + /* Then link back to both. */ + nvmState->frontEnd.wrapper = resultVm; + nvmState->frontEnd.data = resultEnv; + + /* Success! */ + **outVm = resultVm; + *outEnv = resultEnv; + return JNI_OK; + +fail_nvmBoot: +fail_allocResultEnv: + if (resultEnv != NULL) + sjme_alloc_free(resultEnv); +fail_allocResultVm: + if (resultVm != NULL) + sjme_alloc_free(resultVm); + + return JNI_ERR; +} + +/** + * Obtains the default virtual machine configuration. + * + * @param vmArgs A @c JavaVMInitArgs , the @c version field must be set before + * this is called. + * @return Either @c JNI_OK or an error such as if the Java version is not + * supported. + * @since 2024/03/18 + */ +sjme_attrUnused jint JNICALL JNI_GetDefaultJavaVMInitArgs( + sjme_attrInOutNotNull void* vmArgs) +{ + JavaVMInitArgs* args; + + if (vmArgs == NULL) + return JNI_EINVAL; + + /* This is aliased under void. */ + args = vmArgs; + + /* Either too old or too new. */ + if (args->version < JNI_VERSION_1_1 || args->version > JNI_VERSION_1_8) + return JNI_EVERSION; + + /* Indicate that we support this version. */ + args->version = JNI_VERSION_1_8; + + /* Clear these. */ + args->nOptions = 0; + args->options = NULL; + + /* Success! */ + return JNI_OK; +} diff --git a/nanocoat/include/frontend/libjvm/revProto.h b/nanocoat/include/frontend/libjvm/revProto.h index fdca03b37c..09e5700e25 100644 --- a/nanocoat/include/frontend/libjvm/revProto.h +++ b/nanocoat/include/frontend/libjvm/revProto.h @@ -29,9 +29,6 @@ extern "C" { /*--------------------------------------------------------------------------*/ -libjvm_re_int JNI_CreateJavaVM(libjvm_re_undefined8* param_1, - libjvm_re_long* param_2, libjvm_re_undefined8 param_3); - libjvm_re_undefined8 JNI_GetCreatedJavaVMs(libjvm_re_undefined8* param_1, libjvm_re_int param_2, libjvm_re_undefined4* param_3); diff --git a/nanocoat/src/alloc.c b/nanocoat/src/alloc.c index 50b939f92e..21d42d3e7a 100644 --- a/nanocoat/src/alloc.c +++ b/nanocoat/src/alloc.c @@ -325,10 +325,12 @@ sjme_errorCode sjme_alloc_poolInitStatic( #endif /* If this is a valid link then we are allocating a nested pool. */ +#if 0 specialParent = NULL; if (!sjme_error_is(sjme_alloc_getLinkOptional(baseAddr, &specialParent, SJME_JNI_FALSE))) specialParent->flags |= SJME_ALLOC_LINK_FLAG_NESTED_POOL; +#endif /* Use the pool. */ *outPool = pool; -- 2.11.4.GIT