Unable to build java google cloud debugger on ubuntu server on virtualbox - java

I'm trying to build the java google cloud debugger on Ubuntu 15.10 Server (guest) running on Virtual Box 5.0.14 on Mac OS X El Capitan (host).
I'm following the build instructions from cloud-debug-java
After installing cmake, build-essential, oracle java 8, maven3 etc., I also had to make the following changes to src/agent/Makefile before running ./build.sh:
Changed the /path/to/java/ to /usr/lib/jvm/java-8-oracle/
Added this include: -I/usr/lib/jvm/java-8-oracle/include/linux
So, my INCLUDES declaration looks like this:
INCLUDES = \
-I/usr/lib/jvm/java-8-oracle/include \
-I/usr/lib/jvm/java-8-oracle/include/linux \
-I$(THIRD_PARTY_INCLUDE_PATH) \
-I$(ANTLR_CPP_LIB_INCLUDE) \
-I. \
-I../codegen \
-Iantlrgen \
After that, the build runs fine but eventually fails when trying to build expression_util.o
Error:
g++ -I/usr/lib/jvm/java-8-oracle/include -I/usr/lib/jvm/java-8-oracle/include/linux -I/home/ubuntu-java/Development/google-cloud-debugger/cloud-debug-java/third_party/install/include -I../../third_party/antlr/lib/cpp/v2_7_2/ -I. -I../codegen -Iantlrgen -m64 -std=c++11 -fPIC -Werror -Wall -Wno-unused-parameter -Wno-deprecated -Wno-ignored-qualifiers -Wno-sign-compare -Wno-array-bounds -g0 -DSTANDALONE_BUILD -DGCP_HUB_CLIENT -Wno-unused-but-set-variable -Wno-strict-aliasing -O3 -D NDEBUG -c expression_util.cc -o expression_util.o
In file included from expression_util.cc:25:0:
antlrgen/JavaExpressionLexer.hpp:4:54: fatal error: third_party/antlr/lib/cpp/antlr/config.hpp: No such file or directory
compilation terminated.
Makefile:190: recipe for target 'expression_util.o' failed
make: *** [expression_util.o] Error 1
In the generated JavaExpressionLexer.hpp file, it's trying to #include third_party/antlr/lib/cpp/antlr/config.hpp and fails to find it.
In the project, I do see a config.hpp, but it's under <project-root>/third_party/antlr/lib/cpp/v2_7_2/antlr/.
I'm not sure how to resolve this error.

Are you using build.sh script? It should take care of ANTLR and other third party dependencies.
Specifically the build needs to set THIRD_PARTY_INCLUDE_PATH environment variable similarly to build.sh.

Related

Cross-compile JavaFX+Swing desktop application using GraalVM

Background
I'd like to update my JavaFX+Swing desktop application's build process to cross-compile installer-free native binaries for Linux, MacOS, Windows, and JVM targets. The project uses Warp-Packer and BellSoft's FULL version of Liberica OpenJDK 19 to generate a self-extracting, self-running executable for Windows and Linux. In effect, end users can start using the application as follows:
Download the binary.
Run the binary.
I'd like to switch from Warp-Packer to GraalVM for various technical reasons.
Problem
I've tried creating a binary using BellSoft's Native Image Kit, Oracle's GraalVM, and Gluon's GraalVM without success.
Environment
The build environment:
$ java -version
OpenJDK 64-Bit Server VM (build 19.0.1+11, mixed mode, sharing)
$ gradle --version
Gradle 7.6-rc-1
$ uname -a
Linux hostname 6.0.1-arch2-1 #1 SMP PREEMPT_DYNAMIC Thu, 13 Oct 2022 18:58:49 +0000 x86_64 GNU/Linux
Links to the exact versions of OpenJDK and Gradle being used:
https://download.bell-sw.com/java/19.0.1+11/bellsoft-jdk19.0.1+11-linux-amd64-full.tar.gz
https://services.gradle.org/distributions/gradle-7.6-rc-1-bin.zip
The GraalVMs:
BellSoft's Native Image Kit: https://download.bell-sw.com/vm/22.3.0/bellsoft-liberica-vm-full-openjdk17.0.5+8-22.3.0+2-linux-amd64.tar.gz
Oracle's GraalVM: https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.3.0/graalvm-ce-java19-linux-amd64-22.3.0.tar.gz
Gluon's GraalVM: https://github.com/gluonhq/graal/releases/download/gluon-22.1.0.1-Final/graalvm-svm-java17-linux-gluon-22.1.0.1-Final.tar.gz
Note that the application's build.gradle file targets JDK 17:
java {
sourceCompatibility = VERSION_17
targetCompatibility = VERSION_17
}
Further, the application targets JavaFX 19, which could be a problem:
javafx {
version = '19'
modules = ['javafx.controls', 'javafx.swing']
configuration = 'compileOnly'
}
Build
This section provides the complete steps to reproduce the problems I've encountered with each GraalVM implementation.
Native Image Kit
NIK fails due to a bug:
cd /tmp
wget https://download.bell-sw.com/vm/22.3.0/bellsoft-liberica-vm-openjdk17.0.5+8-22.3.0+2-src.tar.gz
mkdir nik
cd nik
tar xf ../bell*gz
grep -n InteropFactoryN graal/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/javafx/JavaFXReflection.java
This shows:
243: "com.sun.javafx.embed.swing.newimpl.InteropFactoryN",
In full context:
static void registerSwing(DuringAnalysisAccess access) {
registerReflectionClasses(access,
"com.sun.javafx.embed.swing.SwingFXUtilsImpl",
"com.sun.javafx.embed.swing.newimpl.InteropFactoryN",
"javafx.embed.swing.SwingNode",
"jdk.swing.interop.LightweightFrameWrapper");
}
If any reflected class doesn't exist, NIK terminates with an error. For example:
Fatal error: org.graalvm.compiler.debug.GraalError: com.oracle.svm.core.util.VMError$HostedError: class com.sun.javafx.embed.swing.newimpl.InteropFactoryN not found
The InteropFactoryN class was removed sometime between javafx-swing 11.0.2 and 12.0.2:
https://repo1.maven.org/maven2/org/openjfx/javafx-swing/11.0.2/javafx-swing-11.0.2-sources.jar
https://repo1.maven.org/maven2/org/openjfx/javafx-swing/12.0.2/javafx-swing-12.0.2-sources.jar
https://repo1.maven.org/maven2/org/openjfx/javafx-swing/17.0.2/javafx-swing-17.0.2-sources.jar
Verified using:
$ jar -tvf javafx-swing-12.0.2-sources.jar | grep FactoryN
$ jar -tvf javafx-swing-17.0.2-sources.jar | grep FactoryN
$ jar -tvf javafx-swing-11.0.2-sources.jar | grep FactoryN
2166 Wed Jan 16 10:19:04 PST 2019 com/sun/javafx/embed/swing/newimpl/InteropFactoryN.java
NIK is built upon OpenJDK 17, and the above confirms that the class was removed and not re-instated. Complete instructions to replicate the bug (Java and Gradle must be installed and available via the PATH):
cd /tmp
git clone https://github.com/DaveJarvis/keenwrite
cd keenwrite
gradle jar
mkdir -p src/main/resources/META-INF/native-image
wget "https://download.bell-sw.com/vm/22.3.0/bellsoft-liberica-vm-full-openjdk17.0.5+8-22.3.0+2-linux-amd64.tar.gz"
tar xf *gz
rm *gz
mv bell* nik
export LD_LIBRARY_PATH="$(pwd)/nik/lib:$LD_LIBRARY_PATH"
# Run the app and use many options.
java \
-agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image \
--add-opens=javafx.controls/javafx.scene.control=ALL-UNNAMED \
--add-opens=javafx.controls/javafx.scene.control.skin=ALL-UNNAMED \
--add-opens=javafx.graphics/javafx.scene.text=ALL-UNNAMED \
--add-opens=javafx.graphics/com.sun.javafx.css=ALL-UNNAMED \
--add-opens=javafx.graphics/com.sun.javafx.text=ALL-UNNAMED \
--add-exports=javafx.base/com.sun.javafx.event=ALL-UNNAMED \
--add-exports=javafx.graphics/com.sun.javafx.application=ALL-UNNAMED \
--add-exports=javafx.graphics/com.sun.javafx.geom=ALL-UNNAMED \
--add-exports=javafx.graphics/com.sun.javafx.text=ALL-UNNAMED \
--add-exports=javafx.graphics/com.sun.javafx.scene=ALL-UNNAMED \
--add-exports=javafx.graphics/com.sun.javafx.scene.text=ALL-UNNAMED \
--add-exports=javafx.graphics/com.sun.javafx.scene.traversal=ALL-UNNAMED \
-jar build/libs/keenwrite.jar $#
# Exit the app when most of the features have been exercised.
# Fails due to missing reflective class, InteropFactoryN.
./nik/bin/native-image \
--add-modules=javafx.controls,javafx.swing \
--verbose \
-H:+ReportExceptionStackTraces \
--no-fallback \
--report-unsupported-elements-at-runtime \
-Djava.awt.headless=false \
-cp src/main/resources/META-INF/native-image \
-jar build/libs/keenwrite.jar
Gluon
Gluon fails because the JavaFX modules cannot be found. Here are the build instructions:
cd /tmp
git clone https://github.com/DaveJarvis/keenwrite
cd keenwrite
gradle clean jar
mkdir -p src/main/resources/META-INF/native-image
wget "https://github.com/gluonhq/graal/releases/download/gluon-22.1.0.1-Final/graalvm-svm-java17-linux-gluon-22.1.0.1-Final.tar.gz"
tar xf *gz
rm *gz
mv graalvm* graalvm
export LD_LIBRARY_PATH="$(pwd)/graalvm/lib:$LD_LIBRARY_PATH"
java \
-agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image \
--add-opens=javafx.controls/javafx.scene.control=ALL-UNNAMED \
--add-opens=javafx.controls/javafx.scene.control.skin=ALL-UNNAMED \
--add-opens=javafx.graphics/javafx.scene.text=ALL-UNNAMED \
--add-opens=javafx.graphics/com.sun.javafx.css=ALL-UNNAMED \
--add-opens=javafx.graphics/com.sun.javafx.text=ALL-UNNAMED \
--add-exports=javafx.base/com.sun.javafx.event=ALL-UNNAMED \
--add-exports=javafx.graphics/com.sun.javafx.application=ALL-UNNAMED \
--add-exports=javafx.graphics/com.sun.javafx.geom=ALL-UNNAMED \
--add-exports=javafx.graphics/com.sun.javafx.text=ALL-UNNAMED \
--add-exports=javafx.graphics/com.sun.javafx.scene=ALL-UNNAMED \
--add-exports=javafx.graphics/com.sun.javafx.scene.text=ALL-UNNAMED \
--add-exports=javafx.graphics/com.sun.javafx.scene.traversal=ALL-UNNAMED \
-jar build/libs/keenwrite.jar $#
./graalvm/bin/native-image \
--verbose \
-H:+ReportExceptionStackTraces \
--no-fallback \
--report-unsupported-elements-at-runtime \
-Djava.awt.headless=false \
-cp src/main/resources/META-INF/native-image \
-jar build/libs/keenwrite.jar
This fails because GraalVM cannot find JavaFX and Swing. I tried a variety of ways to instruct native-image where to find the JavaFX modules, including:
--module-path /opt/jdk/jmods/ --add-modules=javafx.controls,javafx.swing
I've also downloaded both the JavaFX 19 SDK and the JavaFX 19 jmods and tried using them, such as:
--module-path $(pwd)/javafx-sdk-19 --add-modules=...
--module-path $(pwd)/javafx-jmods-19 --add-modules=...
Neither of those approaches worked.
Oracle
Using the regular GraalVM failed well before any JavaFX issues would be encountered:
cd /tmp
git clone https://github.com/DaveJarvis/keenwrite
cd keenwrite
gradle jar
wget https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.3.0/graalvm-ce-java19-linux-amd64-22.3.0.tar.gz
tar xf graalvm*
rm *gz
mv graalvm* graalvm
./graalvm/bin/gu install native-image
./graalvm/bin/native-image \
--verbose \
-H:+ReportExceptionStackTraces \
--no-fallback \
--report-unsupported-elements-at-runtime \
-Djava.awt.headless=false \
-jar build/libs/keenwrite.jar
This results in the following error:
Fatal error: java.lang.RuntimeException: There was an error linking the native image: Linker command exited with 1
I think the error is caused by:
/usr/bin/ld: /tmp/keenwrite/graalvm/lib/static/linux-amd64/glibc/libawt.a(awt_LoadLibrary.o):(.bss.jvm+0x0): multiple definition of `jvm'; /tmp/keenwrite/graalvm/lib/static/linux-amd64/glibc/libawt_xawt.a(XlibWrapper.o):(.bss.jvm+0x0): first defined here
The full log is at:
https://textdoc.co/kweRFKOHDCV9ZE3A
Supplementary build process details are described on my blog.
Question
How do you cross-compile a JavaFX+Swing application using GraalVM to create a native Linux executable on Linux? More specifically, what steps do I need to run to build a native binary for my application using GraalVM?
Bounty
For some reason StackOverflow didn't update the bounty text. Here's the criteria for awarding:
The answer must provide the exact and complete set of commands to run that will produce a native executable on Linux. Further, the binary must be able to open and render an R Markdown file in the GUI as well as export the file to a PDF. That is, no functionality is lost. The resources and resource bundles don't have to work, but it'd be great if they did.

How install python 3.7.7 on adoptopenjdk/openjdk11:x86_64-alpine-jdk-11.0.6_10?

The dockerfile is:
FROM adoptopenjdk/openjdk11:x86_64-alpine-jdk-11.0.6_10
RUN apk update && apk upgrade
# install base modules, python, node.js (java comes with)
RUN apk add --update-cache \
bash \
ttf-dejavu \
python3==3.7.7 \
build-base \
nodejs \
npm \
git \
&& rm -rf /var/cache/apk/*
And this gives me en error:
ERROR: unable to select packages:
python3-3.8.10-r0:
breaks: world[python3=3.7.7]
Any ideas?
It seems like the error is in defining the specific version of python3.
You can set specific versions like this:
# Both are equal
apk add package=1.2.3-suffix
apk add 'package<1.2.3-suffix'
See https://stschindler.medium.com/the-problem-with-docker-and-alpines-package-pinning-18346593e891 Alpine Linux most likely no longer has the package for 3.7.7 that you are asking for

JLink does not produce redistributable image

For a while now I've been working with modular projects, but due to being constrained with filename and automatic modules, I had never got a chance to work with jlink tool to produce a redistributable application image. Today I've opted to start an independent project which does not import any external dependencies to prevent usage of the compatibility mode. The project consists of 3 modules and is in maven, so I will only be posting the jlink command snippet I'm using.
Project for reference: https://gitlab.com/Dragas/edu-day-demo, checkout the modules-full tag. Project is built with package goal, to prevent polluting your local .m2 repository. Project is already configured to pull dependencies so packaging and deployment would be easier.
The command I used to generate the jlinked image was as follows:
jlink \
--module-path edu-day-runtime/target/dependency/:edu-day-runtime/target/ \
--add-modules ALL-MODULE-PATH \
--output edu-day-jlinked \
--launcher edurun=edu.day.runtime
Invoking the command does indeed generate a jlinked image, which contains minimum required modules, java libraries and JVM binaries to run the project. Invoking the machine that built the image
edu-day-jlinked/bin/edurun 1 1
does run the project and outputs the following
Result of sum is 2
Meanwhile, attempting to run the same in containerized environment (here i'm using bash:5, a non-java image to simulate an environment where java is not installed) does not yield similar results. Instead, the shell does not seem to find a binary named java
docker run -it -v "$(pwd)/edu-day-jlinked:/app" bash:5
...(in container)
bash-5.0# /app/bin/edurun 1 1
/app/bin/edurun: line 4: /app/bin/java: not found
Upon inspection, the folder does indeed contain the binary called java
bash-5.0# ls -la
total 52
drwxr-xr-x 2 1000 1000 4096 Aug 23 07:53 .
drwxr-xr-x 7 1000 1000 4096 Aug 23 07:53 ..
-rwxr-xr-x 1 1000 1000 116 Aug 23 07:53 edurun
-rwxr-xr-x 1 1000 1000 16688 Aug 23 07:53 java
-rwxr-xr-x 1 1000 1000 16712 Aug 23 07:53 keytool
But even invoking it directly (to show the help message) does not yield any results, besides the same message that the binary cannot be found
(in /app/bin/ folder)
bash-5.0# ./java
bash: ./java: No such file or directory
What is more interesting is that even the keytool binary returns the same error
(in /app/bin/ folder)
bash-5.0# ./keytool
bash: ./keytool: No such file or directory
This raises a question: what went wrong? I haven't yet delved deeper into how jlink works, but my speculation is that it copies the binaries from my own java installation (openjdk 11.0.8+10 from arch repositories), and considers that to be redistributable. Or did I just miss some command line options?
Your issue is that the test container (bash:5) doesn't use the same version of the run-time linker as the java environment.
The binary produced by the jlink will only run if there is a compatible linux run-time linker on the system.
The purpose of the run-time linker is to configure the binary for execution on the system - at the time you are building an executable the default run-time linker is hard-coded into the binary. You can inspect the run-time linker using a tool such as readelf -l, or ldd (ldd only works if it can find the run-time linker)
The default run-time linker for amd64 linux (e.g. ubuntu) is: /lib64/ld-linux-x86-64.so.2
The default run-time linker for i386 linux is: /lib/ld-linux.so.2
On a bash:5 container, the default run-time linker is: /lib/ld-musl-x86_64.so.1
This is not compatible with the run-time linker for the jdk
The error: /app/bin/java: not found is caused because the run-time linker cannot be found for the binary. A dirty test of a jlinked VM in a bash:5 container gives the same error.
When I get the run-time linker for the java I've used:
$ docker run --rm -it -v (pwd)/edu-day-jlinked64:/app -w /here bash:5 bash
bash-5.0# /app/bin/java
bash: /app/bin/java: No such file or directory
bash-5.0# strings -a /app/bin/java | grep '^/lib'
/lib64/ld-linux-x86-64.so.2
bash-5.0# ls -l /lib64/ld-linux-x86-64.so.2
ls: /lib64/ld-linux-x86-64.so.2: No such file or directory
Testing with the run-time linker that's on-board:
bash-5.0# /lib/ld-musl-x86_64.so.1 --list /app/bin/java
/lib64/ld-linux-x86-64.so.2 (0x7fe2852a3000)
libjli.so => /app/bin/../lib/libjli.so (0x7fe28528c000)
libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7fe2852a3000)
libz.so.1 => /lib/libz.so.1 (0x7fe285272000)
libdl.so.2 => /lib64/ld-linux-x86-64.so.2 (0x7fe2852a3000)
libpthread.so.0 => /lib64/ld-linux-x86-64.so.2 (0x7fe2852a3000)
Error relocating /app/bin/../lib/libjli.so: __snprintf_chk: symbol not found
Error relocating /app/bin/../lib/libjli.so: __vfprintf_chk: symbol not found
Error relocating /app/bin/../lib/libjli.so: __read_chk: symbol not found
Error relocating /app/bin/../lib/libjli.so: __memmove_chk: symbol not found
Error relocating /app/bin/../lib/libjli.so: __printf_chk: symbol not found
Error relocating /app/bin/../lib/libjli.so: __fprintf_chk: symbol not found
Error relocating /app/bin/../lib/libjli.so: __sprintf_chk: symbol not found
so it definitely won't work here.
Let's use something 'standard'. As I had built the jlinked app in an ubuntu:focal container, with an installed version of java let's use one that doesn't have java built-in:
$ docker run --rm -it -v $(pwd)/edu-day-jlinked64:/app -w /here ubuntu:focal bash
root#865c9c12c029:/here# /app/bin/java
Usage: java [options] <mainclass> [args...]
(to execute a class)
or java [options] -jar <jarfile> [args...]
(to execute a jar file)
or java [options] -m <module>[/<mainclass>] [args...]
java [options] --module <module>[/<mainclass>] [args...]
(to execute the main class in a module)
or java [options] <sourcefile> [args]
(to execute a single source-file program)
so it will work in this case.
Reproducibility:
Built using:
$ docker run --rm -it -v $(pwd):/here -w /here ubuntu:focal bash
# apt-get update
# DEBIAN_FRONTEND=noninteractive apt-get install -y git openjdk-14-jdk maven
# git clone https://gitlab.com/Dragas/edu-day-demo .
# git checkout modules-full
# ./mvnw package
# rm -rf edu-day-runtime/target/classes
# jlink --module-path edu-day-runtime/target/dependency/:edu-day-runtime/target/ --add-modules ALL-MODULE-PATH --output edu-day-jlinked --launcher edurun=edu.day.runtime
# ./edu-day-jlinked/bin/edurun 1 1
Result of sum is 2
In an adjacent directory:
$ docker run --rm -it -v $(pwd)/edu-day-jlinked:/app -w /here bash:5 bash
bash-5.0# /app/bin/edurun 1 1
/app/bin/edurun: line 4: /app/bin/java: not found
In another directory:
$ docker run --rm -it -v $(pwd)/edu-day-jlinked:/app -w /here ubuntu:focal bash
root#200b4a98f9ee:/here# /app/bin/edurun 1 1
Result of sum is 2
TL;DR — The bash:5 image uses a C library that is binary incompatible with the C library that was linked with your edu-day-jlinked/bin/java executable.
The long version
„…This raises a question: what went wrong?…“
What's going wrong is your app/bin/java binary is failing to find the C library that it was originally linked to when you built your edu-day-jlinked executable on whatever machine you built it on locally.
The problem occurs because the java binary that jlink produced is linked to the GNU glibc library that your locally-installed JDK uses…
$ ldd edu-day-demo-modules-full/edu-day-jlinked/bin/java
…
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa61a95b000)
…
Whereas, the bash:5 image runs in the Busybox Linux distribution. And Busybox does not use glibc…
bash-5.0# ldd app/bin/java
…
libjli.so => app/bin/../lib/jli/libjli.so (0x7f572a16d000)
…
libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7f572a19f000)
Error relocating app/bin/../lib/jli/libjli.so: __snprintf_chk: symbol not found
Error relocating app/bin/../lib/jli/libjli.so: __vfprintf_chk: symbol not found
Error relocating app/bin/../lib/jli/libjli.so: __read_chk: symbol not found
Error relocating app/bin/../lib/jli/libjli.so: __memmove_chk: symbol not found
Error relocating app/bin/../lib/jli/libjli.so: __printf_chk: symbol not found
Error relocating app/bin/../lib/jli/libjli.so: __fprintf_chk: symbol not found
Error relocating app/bin/../lib/jli/libjli.so: __sprintf_chk: symbol not found
It uses a different C library: musl…
bash-5.0# find / -name '*musl*'
/lib/libc.musl-x86_64.so.1
/lib/ld-musl-x86_64.so.1
It helps to understand the Linking process. And it also helps to bear in mind that JLink builds a custom executable for a specific environment.
Your trial run on your local machine worked, because jlink built the executable specifically for your local environment.
The proposed solution
„…docker here is intended to simulate an environment which does not have java installed…“
Here is a Dockerfile that successfully builds your application and the resulting image „does not have java installed“…
FROM maven:3.6.1-jdk-13-alpine as build
WORKDIR /app
COPY pom.xml .
COPY edu-day-sum edu-day-sum
COPY edu-day-runtime edu-day-runtime
COPY edu-day-api edu-day-api
RUN mvn package && \
--module-path ${JAVA_HOME}/jmods:edu-day-runtime/target/dependency/:edu-day-runtime/target/edu-day-runtime-1.0-SNAPSHOT.jar \
--add-modules ALL-MODULE-PATH \
--output edu-day-jlinked \
--launcher edurun=edu.day.runtime
FROM alpine:latest
COPY --from=build /app/edu-day-jlinked /app
ENTRYPOINT ["/app/bin/edurun"]
CMD ["1", "1"]
Docker best practice advises: „Use multi-stage builds“ (like in the above Dockerfile) when your aim is to build „an environment which does not have java installed“.
The FROM maven:3.6.1-jdk-13-alpine stage of the multi-stage build, uses an alpine Linux image that has both Maven and a JDK specifically built to be compatible with the alpine distribution.
The FROM alpine:latest is a very small linux distro that does not have Java on it. The maven:3.6.1-jdk-13-alpine layer is discarded as the Docker best practice docs says. The only java in the resulting image is the one in app/bin.

"Unable to run a simple JNI program" error message when installing rJava on R 3.6 for ubuntu bionic beaver

I have the very common problem that rJava does not install correctly on Ubuntu.
This problem has been dsicussed in multiple places here, here, here, to name a few.
The basic problem is that on installing the rJava package, the following error message is produced
configure: error: Unable to run a simple JNI program. Make sure you have configured R with Java support (see R documentation) and check config.log for failure reason.
Warning in system(cmd) : error in running command
ERROR: configuration failed for package ‘rJava’
* removing ‘/home/jonno/R/x86_64-pc-linux-gnu-library/3.6/rJava’
There are various closely related solutions to this problem. Most of them use sudo R CMD javareconf to configure Java for R (also a -e variant). Some suggest setting the JAVA_HOME path in the environment variables (others say not to). Others suggest uninstalling and re-installing R whilst others suggest installing rJava from cran. There are several who reccomend update alternatives. There are other variants of these solutions.
I have tried combinations of all of the above, and have got nowhere, so am clearly doing something wrong.
entering echo $JAVA_HOME returns
/usr/lib/jvm/java-11-openjdk-amd64
my etc/environment looks like this
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/$
MKL_THREADING_LAYER=GNU
JAVA_HOME="/usr/lib/jvm/java-11-openjdk-amd64"
When I run R CMD javaconf, it looks like this
Java interpreter : /usr/lib/jvm/java-11-openjdk-amd64/java
Java version : 11.0.4
Java home path : /usr/lib/jvm/java-11-openjdk-amd64
Java compiler : /usr/lib/jvm/java-11-openjdk-amd64/bin/javac
Java headers gen.: /usr/bin/javah
Java archive tool: /usr/lib/jvm/java-11-openjdk-amd64/bin/jar
trying to compile and link a JNI program
detected JNI cpp flags : -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux
detected JNI linker flags : -L$(JAVA_HOME)/lib/server -ljvm
gcc -std=gnu99 -I"/usr/share/R/include" -DNDEBUG -I/usr/lib/jvm/java-11-openjdk-amd64/include -I/usr/lib/jvm/java-11-openjdk-amd64/include/linux -fpic -g -O2 -fdebug-prefix-map=/build/r-base-uuRxut/r-base-3.6.1=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c conftest.c -o conftest.o
gcc -std=gnu99 -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o conftest.so conftest.o -L/usr/lib/jvm/java-11-openjdk-amd64/lib/server -ljvm -L/usr/lib/R/lib -lR
JAVA_HOME : /usr/lib/jvm/java-11-openjdk-amd64
Java library path: $(JAVA_HOME)/lib/server
JNI cpp flags : -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux
JNI linker flags : -L$(JAVA_HOME)/lib/server -ljvm
Updating Java configuration in /usr/lib/R
Done.
What am I doing wrong and how do I get rJava to install properly?
EDIT:
having managed to successfully install rJava using sudo apt-get install r-cran-rjava I know get the following error
Error: package or namespace load failed for ‘rJava’:
.onLoad failed in loadNamespace() for 'rJava', details:
call: dyn.load(file, DLLpath = DLLpath, ...)
error: unable to load shared object '/usr/lib/R/site-library/rJava/libs/rJava.so':
libjvm.so: cannot open shared object file: No such file or directory
I've investigated with the original poster (we work at the same place) and the problem is that in OpenJDK11 they moved around some of the .so files that the JVM lives in, specifically libjvm.so which in the Ubuntu package is now in /usr/lib/jvm/java-1.11.0-openjdk-amd64/lib/server/.
This means that even if you install the Ubuntu package for rJava with apt install r-cran-rjava it fails when you try to library(rJava).
The solution is to add /usr/lib/jvm/java-1.11.0-openjdk-amd64/lib/server/ to your $LD_LIBRARY_PATH by adding:
export LD_LIBRARY_PATH=/usr/lib/jvm/java-1.11.0-openjdk-amd64/lib/server:$LD_LIBRARY_PATH
to the end of your ~/.bashrc and starting a new shell (or source ~/.bashrc).
This is something we had to fix for our central installs of OpenJDK e.g. here: https://github.com/UCL-RITS/rcps-buildscripts/blob/master/adoptopenjdk-11.0.3_install.sh#L46
If you want to make this work with Rstudio launched from Gnome, you need to add that directory to ldconfig.
As root (or with sudo) create a file in /etc/ld.so.conf.d/ which you should call something with a .conf extension e.g. java.conf which contains the line:
/usr/lib/jvm/java-1.11.0-openjdk-amd64/lib/server
And then as root run
ldconfig -v
This should add the directory to the locations that executables launched through GNOME search for. This particular part of the problem (GNOME ignoring settings in bashrc) has been a problem in Ubuntu since at least 9.04 (https://bugs.launchpad.net/ubuntu/+source/xorg/+bug/366728/).

How to cross compile my C code containing JNI?

Previously I asked a question related to calling java function at
Calling Java functions from C language
Somehow I did with that.
Now I am planning to cross compile that.
I am facing an issue.
Before cross compiling ( means compiling in the same pc for the same pc)
I used the commands
gcc -I /usr/lib/jvm/java-6-openjdk-amd64/include -I /usr/lib/jvm/java-6-openjdk-amd64/include/linux -L /usr/bin/java -L /usr/lib/jvm/java-6-openjdk-amd64/jre/lib/amd64/server MyC.c -ljvm ;
That created well.
But now I am trying to cross compile the same for my target arm-none-eabi-
My makefile
CROSS_COMPILE =arm-none-eabi-
JAVA_HOME =/usr/lib/jvm/java-7-openjdk-amd64/
test:
javac -d ./ MyJava.java
$(CROSS_COMPILE)gcc -I $(JAVA_HOME)include \
-I $(JAVA_HOME)include/linux \
-L $(JAVA_HOME)jre/lib/amd64/server \
MyC.c -ljvm
This returning error
arm-none-eabi/bin/ld: warning: library search path "/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/server" is unsafe for cross-compilation
/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/server/libjvm.so: file not recognized: File format not recognized
collect2: ld returned 1 exit status
make: *** [test] Error 1

Categories