This is an automated email from the ASF dual-hosted git repository. leginee pushed a commit to branch bazel-migration in repository https://gitbox.apache.org/repos/asf/openoffice.git
commit af1706569a19941eadb9310a9601ba48bb02867c Author: Peter Kovacs <[email protected]> AuthorDate: Wed Aug 5 08:03:26 2026 +0200 build(stoc): build javaloader.uno + javavm.uno — the Java2 loader was missing First step of the Java bucket, and it turned out not to be javamaker (already built) but the fact that com.sun.star.loader.Java2 had no implementation at all. javaloader.uno.dll (com.sun.star.comp.stoc.JavaComponentLoader — builds a class loader over a component's jar and calls its RegistrationClassName) and javavm.uno.dll (com.sun.star.comp.stoc.JavaVirtualMachine — locates/starts the JVM via jvmfwk) were NEVER BUILT, while both were registered in services.rdb MAPPED TO bootstrap.uno.dll as a placeholder. That could never work: neither implementation is in that DLL, so any Java UNO component would fail to instantiate however it was registered. Both are now built, staged, and registered at their real DLLs. Upstream gates them behind SOLAR_JAVA; unconditional here, since the Bazel build always has a JDK toolchain (rules_java is a hard dep). Two landmines, both in the C++/JNI seam: SOLAR_JAVA IS LOAD-BEARING, not a feature switch. jvmaccess/virtualmachine.hxx #includes the real <jni.h> only under it, and otherwise declares stubs (struct JNIEnv;, typedef void * jobject;). Without it every JNIEnv-> call is C2027 "use of undefined type" — even in javaloader.cxx, which #includes "jni.h" ITSELF, because the incomplete stub is already in scope by then. Same landmine as the java_uno JNI bridge in //main/bridges. javavm needs /Zc:wchar_t-, javaloader does not. javavm.cxx passes sal_Unicode* straight into JNI calls (NewString, GetStringRegion). On Windows sal_Unicode IS wchar_t (sal/types.h), and with native wchar_t that is a distinct type from jchar (unsigned short), so every such call is C2664 "types pointed to are unrelated". /Zc:wchar_t- makes wchar_t == unsigned short == jchar. javaloader escapes it by only ever handing JNI plain UTF-8 (NewStringUTF). NOT yet sufficient to RUN a Java component — the DLLs are necessary, not sufficient. Remaining chain, in the order javavm.cxx::getJavaVM walks it: 1. URE_INTERNAL_JAVA_DIR must be expandable by theMacroExpander, which resolves against the URE_BOOTSTRAP file — program/fundamental.ini, NOT uno.ini. staging/uno.ini already sets it (and URE_INTERNAL_JAVA_CLASSPATH); fundamental.ini does not, and that is the one that counts — the same trap the extension-path macros already hit. 2. program/classes/ staging does not exist. getJavaVM bootstraps from $URE_INTERNAL_JAVA_DIR/unoloader.jar → URLClassLoader → UnoClassLoader, which then builds the real classpath. Every jar target already exists (ridljar:unoloader, jurt, juh_jar, bridges:java_uno_jar, unoil) but stage_install.bzl has no classes/ destination. 3. jvmfwk needs a JRE to find (javavendors.xml + jvmfwk3 config), not staged. So the next step is staging, not compilation. See main/stoc/readme.md. Verified: both DLLs compile and link; //main/staging:install and //main/postprocess:services_rdb still analyse clean. Co-Authored-By: Claude Opus 5 <[email protected]> --- main/postprocess/BUILD.bazel | 12 ++++-- main/staging/BUILD.bazel | 9 ++++ main/stoc/BUILD.bazel | 100 +++++++++++++++++++++++++++++++++++++++++++ main/stoc/readme.md | 91 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 207 insertions(+), 5 deletions(-) diff --git a/main/postprocess/BUILD.bazel b/main/postprocess/BUILD.bazel index 2355f7c8b9..639e1d8426 100644 --- a/main/postprocess/BUILD.bazel +++ b/main/postprocess/BUILD.bazel @@ -47,12 +47,16 @@ _SERVICES_COMPONENTS = { basis_native("invocadapt.uno.dll"), "//main/stoc:source/invocation/invocation.component": basis_native("invocation.uno.dll"), - # javaloader/javavm: Java components (deferred) — still mapped to - # bootstrap.uno.dll (not built; only loaded if Java is used). + # javaloader/javavm — the two halves of com.sun.star.loader.Java2, i.e. + # what makes loading a UNO component written in Java possible at all. + # They used to be mapped to bootstrap.uno.dll as a PLACEHOLDER, which could + # never work: neither implementation is in that DLL, so any Java component + # would fail to instantiate no matter how it was registered. Both are now + # built (//main/stoc) and staged, so point at them for real. "//main/stoc:source/javaloader/javaloader.component": - basis_native("bootstrap.uno.dll"), + basis_native("javaloader.uno.dll"), "//main/stoc:source/javavm/javavm.component": - basis_native("bootstrap.uno.dll"), + basis_native("javavm.uno.dll"), "//main/stoc:source/namingservice/namingservice.component": basis_native("namingservice.uno.dll"), "//main/stoc:source/proxy_factory/proxyfac.component": diff --git a/main/staging/BUILD.bazel b/main/staging/BUILD.bazel index 79f05f2099..02fb4fa870 100644 --- a/main/staging/BUILD.bazel +++ b/main/staging/BUILD.bazel @@ -83,6 +83,15 @@ collect_outputs( # (java_uno.jar) needs the program/classes/ classpath staging, which does # not exist yet — see readme.md "jni_uno" notes. "//main/bridges:java_uno", + # com.sun.star.loader.Java2, in two halves: javavm starts/locates the + # JVM through jvmfwk, javaloader is the loader that builds a class + # loader over a component's jar. Registered in services.rdb by + # //main/postprocess. NOTE these being present is necessary but NOT + # sufficient to run a Java component — program/classes/ staging and the + # URE_INTERNAL_JAVA_DIR bootstrap variable are still missing; see + # main/stoc/readme.md. + "//main/stoc:javaloader.uno", + "//main/stoc:javavm.uno", "//main/io:streams", "//main/io:acceptor", "//main/io:connector", diff --git a/main/stoc/BUILD.bazel b/main/stoc/BUILD.bazel index 14998bc85e..83209aef5a 100644 --- a/main/stoc/BUILD.bazel +++ b/main/stoc/BUILD.bazel @@ -210,5 +210,105 @@ _REFL_COMPONENTS = { for _name, _srcs in _REFL_COMPONENTS.items() ] +# ── Java UNO loader: javaloader.uno.dll + javavm.uno.dll ────────── +# These two are what makes `com.sun.star.loader.Java2` real, i.e. what lets the +# office load a UNO component written in Java at all. Until now both were +# registered in services.rdb but MAPPED TO bootstrap.uno.dll as a placeholder +# (postprocess/BUILD.bazel), which cannot work — neither implementation is in +# that DLL, so any Java component would fail to instantiate. +# * javavm.uno.dll — com.sun.star.comp.stoc.JavaVirtualMachine: starts / +# locates the JVM through jvmfwk and hands out a jvmaccess::VirtualMachine. +# * javaloader.uno.dll — com.sun.star.comp.stoc.JavaComponentLoader: the +# Java2 loader itself; builds a class loader over the component's jar and +# calls its RegistrationClassName. +# Upstream gates both behind SOLAR_JAVA; here they are unconditional, because +# the Bazel build always has a JDK toolchain (rules_java is a hard dep). +# +# They do not fit _REFL_COMPONENTS: both need jvmaccess, javavm additionally +# needs jvmfwk, the JNI headers and advapi32 (it reads the registry to find an +# installed JRE). +# SOLAR_JAVA is LOAD-BEARING, not just a feature switch: jvmaccess/ +# virtualmachine.hxx #includes the real <jni.h> only under it, and otherwise +# declares stubs (`struct JNIEnv;`, `typedef void * jobject;`). Without it +# every JNIEnv-> call is C2027 "use of undefined type", even though the file +# #includes "jni.h" itself — the stub declaration is what the compiler already +# has by then. Same landmine as the java_uno JNI bridge (//main/bridges). +_JAVA_LOADER_DEFINES = _DEFINES + ["SOLAR_JAVA"] + +_JAVA_LOADER_IMPLIBS = _REFL_IMPLIBS + [ + "//main/jvmaccess:jvmaccess3MSC_implib", +] + +_JAVA_LOADER_LINKOPTS = [ + "$(execpath //main/sal:sal_implib)", + "$(execpath //main/salhelper:salhelper_implib)", + "$(execpath //main/cppu:cppu3_implib)", + "$(execpath //main/cppuhelper:cppuhelper_implib)", + "$(execpath //main/registry:reg_implib)", + "$(execpath //main/jvmaccess:jvmaccess3MSC_implib)", + "/MANIFEST:NO", +] + +cc_binary( + name = "javaloader.uno", + srcs = ["source/javaloader/javaloader.cxx"], + copts = _COPTS, + defines = _JAVA_LOADER_DEFINES, + deps = _DEPS + [ + "//main/jvmaccess:jvmaccess_headers", + # javaloader.cxx calls JNIEnv methods but never #includes <jni.h>: it + # gets only the forward declaration from jvmaccess/virtualmachine.hxx + # and relies on the build system's JAVAINCLUDES (dmake supplies those + # from settings.mk when SOLAR_JAVA=TRUE). Without this the whole file + # is C2027 "use of undefined type 'JNIEnv'". + "@rules_java//toolchains:jni", + ], + additional_linker_inputs = _JAVA_LOADER_IMPLIBS, + linkshared = True, + win_def_file = "util/component.def", + linkopts = _JAVA_LOADER_LINKOPTS, + visibility = ["//visibility:public"], +) + +cc_binary( + name = "javavm.uno", + srcs = [ + "source/javavm/interact.cxx", + "source/javavm/interact.hxx", + "source/javavm/javavm.cxx", + "source/javavm/javavm.hxx", + "source/javavm/jvmargs.cxx", + "source/javavm/jvmargs.hxx", + ], + # /Zc:wchar_t- — javavm.cxx passes sal_Unicode* straight into JNI calls + # (NewString, GetStringRegion). On Windows sal_Unicode IS wchar_t + # (sal/types.h), and with NATIVE wchar_t that is a distinct type from + # jchar (unsigned short), so every one of those calls is C2664 "types + # pointed to are unrelated". /Zc:wchar_t- makes wchar_t == unsigned short + # == jchar and they line up. Exactly the same reason //main/bridges builds + # the jni_uno sources this way; javaloader.uno needs no such thing because + # it only ever hands JNI plain UTF-8 (NewStringUTF). + copts = _COPTS + ["/Zc:wchar_t-"], + defines = _JAVA_LOADER_DEFINES, + deps = _DEPS + [ + "//main/jvmaccess:jvmaccess_headers", + "//main/jvmfwk:jvmfwk_headers", + # jni.h / jni_md.h from the toolchain JDK — same dep the java_uno JNI + # bridge uses, so the two cannot disagree on JNI version. + "@rules_java//toolchains:jni", + ], + additional_linker_inputs = _JAVA_LOADER_IMPLIBS + [ + "//main/jvmfwk:jvmfwk3_implib", + ], + linkshared = True, + win_def_file = "util/component.def", + linkopts = _JAVA_LOADER_LINKOPTS + [ + "$(execpath //main/jvmfwk:jvmfwk3_implib)", + # javavm.cxx reads the JRE location out of the Windows registry. + "advapi32.lib", + ], + visibility = ["//visibility:public"], +) + exports_files(glob(["**/*.component"])) diff --git a/main/stoc/readme.md b/main/stoc/readme.md index be5d1c05f4..e52908376e 100644 --- a/main/stoc/readme.md +++ b/main/stoc/readme.md @@ -1,19 +1,108 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> + # Notes for stoc (done) -- javavm/javaloader/jvmfwk/jvmaccess skipped — only C++ URE components needed +- javaloader + javavm now BUILT (see below). jvmfwk/jvmaccess are their own + modules and were already migrated. ## bootstrap.uno.dll + 9 sub-components merged into one DLL: bootstrap, security, servicemanager, simpleregistry, defaultregistry, implementationregistration, loader, registry_tdprovider, tdmanager ## stocservices.uno.dll + stocservices + typeconv + uriproc ## unistd.h stub + `unistd.h` included unconditionally in implreg.cxx — satisfied by `main/soltools/winunistd/unistd.h` stub. Add `/Imain/soltools/winunistd` to copts wherever this pattern appears in other modules. ## DEF exports + Standard UNO unloadable component pattern — same for all future component DLLs: `component_getImplementationEnvironment`, `component_getFactory`, `component_canUnload` + +## javaloader.uno.dll + javavm.uno.dll — enabling `com.sun.star.loader.Java2` + +These two are what makes loading a UNO component *written in Java* possible at +all: + +- **`javavm.uno.dll`** — `com.sun.star.comp.stoc.JavaVirtualMachine`: locates + and starts the JVM through `jvmfwk`, hands out a `jvmaccess::VirtualMachine`. +- **`javaloader.uno.dll`** — `com.sun.star.comp.stoc.JavaComponentLoader`: the + Java2 loader; builds a class loader over a component's jar and calls its + `RegistrationClassName`. + +Until now **neither was built**, while both were registered in `services.rdb` +*mapped to `bootstrap.uno.dll`* as a placeholder. That could never work — +neither implementation is in that DLL — so any Java component would have failed +to instantiate however it was registered. Both are now built, staged, and +registered at their real DLLs. + +Upstream gates both behind `SOLAR_JAVA`; here they are unconditional, because +the Bazel build always has a JDK toolchain (`rules_java` is a hard dep). + +### Two landmines, both in the C++/JNI seam + +**`SOLAR_JAVA` is load-bearing, not a feature switch.** +`jvmaccess/virtualmachine.hxx` `#include`s the real `<jni.h>` *only* under it, +and otherwise declares stubs (`struct JNIEnv;`, `typedef void * jobject;`). +Without it every `JNIEnv->` call is `C2027 "use of undefined type 'JNIEnv'"` — +even in `javaloader.cxx`, which `#include`s `"jni.h"` itself, because the +incomplete stub is already in scope by then. Same landmine as the java_uno JNI +bridge in `//main/bridges`. + +**`javavm` needs `/Zc:wchar_t-`; `javaloader` does not.** `javavm.cxx` passes +`sal_Unicode*` straight into JNI calls (`NewString`, `GetStringRegion`). On +Windows `sal_Unicode` *is* `wchar_t` (`sal/types.h`), and with native `wchar_t` +that is a distinct type from `jchar` (`unsigned short`) — so every such call is +`C2664 "types pointed to are unrelated"`. `/Zc:wchar_t-` makes +`wchar_t == unsigned short == jchar`. `javaloader` escapes this because it only +ever hands JNI plain UTF-8 (`NewStringUTF`). + +### NOT yet sufficient to run a Java component + +Having the DLLs is necessary but not enough. The remaining chain, in the order +`javavm.cxx::getJavaVM` walks it: + +1. **`URE_INTERNAL_JAVA_DIR` must be expandable** by + `com.sun.star.util.theMacroExpander`, which resolves against the + `URE_BOOTSTRAP` file — i.e. `program/fundamental.ini`, **not** `uno.ini`. + `main/staging/uno.ini` already sets `URE_INTERNAL_JAVA_DIR=${ORIGIN}/classes` + and `URE_INTERNAL_JAVA_CLASSPATH=${URE_MORE_JAVA_CLASSPATH_URLS}`, but + `fundamental.ini` does not — and that is the one that counts. Same trap the + extension-path macros already hit; see the long comment in + `main/staging/fundamental.ini`. `URE_INTERNAL_JAVA_CLASSPATH` is allowed to + be unexpandable, `URE_INTERNAL_JAVA_DIR` is not. +2. **`program/classes/` staging does not exist.** `getJavaVM` bootstraps from + `$URE_INTERNAL_JAVA_DIR/unoloader.jar` → `URLClassLoader` → + `com.sun.star.lib.unoloader.UnoClassLoader`, which then builds the real + classpath. Every jar target already exists — `//main/ridljar:unoloader`, + `//main/jurt:jurt`, `//main/javaunohelper:juh_jar`, + `//main/bridges:java_uno_jar`, `//main/unoil:unoil` — but + `stage_install.bzl` has no `classes/` destination for them. +3. **`jvmfwk` needs a JRE to find.** `javavendors.xml` plus the `jvmfwk3` + config decide which JVM is selected; without them `jvmfwk` reports no JRE + and `javavm` throws. Not yet staged. + +So the next Java-bucket step is **staging, not compilation**.
