Add Java demo

This commit is contained in:
LI Qing 2020-07-16 13:30:50 +08:00 committed by Tate, Hongliang Tian
parent 81eb364c5b
commit 1f30d75713
13 changed files with 267 additions and 8 deletions

@ -15,14 +15,20 @@ This set of demos shows how the Occlum toolchain can be used with different buil
This set of demos shows how real-world apps can be easily run inside SGX enclaves with Occlum. This set of demos shows how real-world apps can be easily run inside SGX enclaves with Occlum.
* [https_server](https_server/): A HTTPS file server based on [Mongoose Embedded Web Server Library](https://github.com/cesanta/mongoose). * [https_server](https_server/): A HTTPS file server based on [Mongoose Embedded Web Server Library](https://github.com/cesanta/mongoose).
* [golang](golang/): A [Golang](https://golang.org) web server demo app. * [grpc](grpc/): A client and server communicating through [gRPC](https://grpc.io).
* [grpc](grpc/): A client and server communicating through [gRPC](https://grpc.io/).
* [openvino](openvino/) A benchmark of [OpenVINO Inference Engine](https://docs.openvinotoolkit.org/2019_R3/_docs_IE_DG_inference_engine_intro.html). * [openvino](openvino/) A benchmark of [OpenVINO Inference Engine](https://docs.openvinotoolkit.org/2019_R3/_docs_IE_DG_inference_engine_intro.html).
* [python](python/) A demo of [Python](https://www.python.org).
* [rust](rust/) A demo of [Rust](https://www.rust-lang.org/).
* [sqlite](sqlite/) A demo of [SQLite](https://www.sqlite.org) SQL database engine. * [sqlite](sqlite/) A demo of [SQLite](https://www.sqlite.org) SQL database engine.
* [tensorflow_lite](tensorflow_lite/): A demo and benchmark of [Tensorflow Lite](https://www.tensorflow.org/lite) inference engine. * [tensorflow_lite](tensorflow_lite/): A demo and benchmark of [Tensorflow Lite](https://www.tensorflow.org/lite) inference engine.
* [xgboost](xgboost/): A demo of [XGBoost](https://xgboost.readthedocs.io/en/latest/). * [xgboost](xgboost/): A demo of [XGBoost](https://xgboost.readthedocs.io/en/latest).
## Programming language demos
This set of demos shows how apps written with popular programming languages can be run inside SGX enclaves with Occlum.
* [golang](golang/): A [Golang](https://golang.org) web server demo app.
* [java](java/): A demo of [Java](https://openjdk.java.net) program.
* [python](python/) A demo of [Python](https://www.python.org) program.
* [rust](rust/) A demo of [Rust](https://www.rust-lang.org) program.
## Other demos ## Other demos

@ -16,7 +16,8 @@ fi
rm -rf occlum_context && mkdir occlum_context rm -rf occlum_context && mkdir occlum_context
cd occlum_context cd occlum_context
occlum init occlum init
new_json="$(jq '.resource_limits.user_space_size = "380MB" | .process.default_mmap_size = "300MB"' Occlum.json)" && \ new_json="$(jq '.resource_limits.user_space_size = "380MB" |
.process.default_mmap_size = "300MB"' Occlum.json)" && \
echo "${new_json}" > Occlum.json echo "${new_json}" > Occlum.json
# 2. Copy program into Occlum Workspace and build # 2. Copy program into Occlum Workspace and build

3
demos/java/.gitignore vendored Normal file

@ -0,0 +1,3 @@
occlum_context/
gs-messaging-stomp-websocket/
*/*.class

50
demos/java/README.md Normal file

@ -0,0 +1,50 @@
# Use Java with Occlum
This project demonstrates how Occlum enables _unmodified_ Java programs running in SGX enclaves.
# About JDK
JDK 11 is supported currently. The source code of JDK 11 can be found [here](https://hg.openjdk.java.net/portola/jdk11). In order for it to cooperate with Occlum, a [minor modification](../../tools/toolchains/java/) has been made to it. The modified JDK is compiled in Alpine Linux with `bash configure && make images` commands. We have installed it at `/opt/occlum/toolchains/jvm/java-11-openjdk/jre` while making the Docker image.
## Demo: Hello World
We provide a "Hello World" demo to show how to run a simple Java program inside SGX enclaves. The demo code can be found [here](hello_world/).
### How to Run
Step 1: Compile the source code with `occlum-javac`
```
occlum-javac ./hello_world/Main.java
```
When completed, the resulting file can be found at `./hello_world/Main.class`.
Step 2: Start JVM to run the hello world program
```
./run_java_on_occlum.sh hello
```
## Demo: Web application with Spring Boot
We also choose a Java web application that using WebSocket with [Spring Boot](https://spring.io/projects/spring-boot). The demo code can be found [here](https://github.com/spring-guides/gs-messaging-stomp-websocket).
### How to Run
Step 1: Download the demo code and build a Fat JAR file with Maven
```
./download_and_build_web_app.sh
```
When completed, the resulting Fat JAR file can be found at `./gs-messaging-stomp-websocket/complete/target/gs-messaging-stomp-websocket-0.1.0.jar`.
Step 2: Start JVM to run the JAR file on Occlum
```
./run_java_on_occlum.sh web_app
```
The web application should now start to listen on port 8080 and serve requests.
Step 3: To check whether it works, run
```
curl http://localhost:8080
```
in another terminal.
It is recommended to access the web application in a Web browser. You have to manually map port 8080 of the Docker container to a port on the host OS. Check out how to use [the `-p` argument of `docker run` command](https://docs.docker.com/engine/reference/commandline/run/).

@ -0,0 +1,14 @@
#!/bin/bash
set -e
# 1. Download the demo
rm -rf gs-messaging-stomp-websocket && mkdir gs-messaging-stomp-websocket
cd gs-messaging-stomp-websocket
git clone https://github.com/spring-guides/gs-messaging-stomp-websocket.git .
git checkout -b 2.1.6.RELEASE tags/2.1.6.RELEASE
# 2. Build the Fat JAR file with Maven
cd complete
export LD_LIBRARY_PATH=/opt/occlum/toolchains/gcc/x86_64-linux-musl/lib
export JAVA_HOME=/opt/occlum/toolchains/jvm/java-11-openjdk/jre
./mvnw clean package

@ -0,0 +1,5 @@
public class Main {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}

@ -0,0 +1,85 @@
#!/bin/bash
set -e
BLUE='\033[1;34m'
NC='\033[0m'
show_usage() {
echo "Error: invalid arguments"
echo "Usage: $0 web_app/hello"
exit 1
}
check_file_exist() {
file=$1
if [ ! -f ${file} ];then
echo "Error: cannot stat file '${file}'"
echo "Please see README and build it"
exit 1
fi
}
init_workspace() {
# Init Occlum Workspace
rm -rf occlum_context && mkdir occlum_context
cd occlum_context
occlum init
new_json="$(jq '.resource_limits.user_space_size = "1400MB" |
.resource_limits.kernel_space_heap_size="64MB" |
.resource_limits.max_num_of_threads = 64 |
.process.default_heap_size = "256MB" |
.process.default_mmap_size = "1120MB" |
.entry_points = [ "/usr/lib/jvm/java-11-openjdk/jre/bin" ] |
.env.default = [ "LD_LIBRARY_PATH=/usr/lib/jvm/java-11-openjdk/jre/lib/server:/usr/lib/jvm/java-11-openjdk/jre/lib:/usr/lib/jvm/java-11-openjdk/jre/../lib" ]' Occlum.json)" && \
echo "${new_json}" > Occlum.json
}
build_web() {
# Copy JVM and JAR file into Occlum Workspace and build
mkdir -p image/usr/lib
cp -r /opt/occlum/toolchains/jvm image/usr/lib/
cp /usr/local/occlum/x86_64-linux-musl/lib/libz.so.1 image/lib
mkdir -p image/usr/lib/spring
cp ../${jar_path} image/usr/lib/spring/
occlum build
}
run_web() {
jar_path=./gs-messaging-stomp-websocket/complete/target/gs-messaging-stomp-websocket-0.1.0.jar
check_file_exist ${jar_path}
jar_file=`basename "${jar_path}"`
init_workspace
build_web
echo -e "${BLUE}occlum run JVM web app${NC}"
occlum run /usr/lib/jvm/java-11-openjdk/jre/bin/java -Xmx512m -XX:MaxMetaspaceSize=64m -Dos.name=Linux -jar /usr/lib/spring/${jar_file}
}
build_hello() {
# Copy JVM and class file into Occlum Workspace and build
mkdir -p image/usr/lib
cp -r /opt/occlum/toolchains/jvm image/usr/lib/
cp /usr/local/occlum/x86_64-linux-musl/lib/libz.so.1 image/lib
cp ../${hello} image
occlum build
}
run_hello() {
hello=./hello_world/Main.class
check_file_exist ${hello}
init_workspace
build_hello
echo -e "${BLUE}occlum run JVM hello${NC}"
occlum run /usr/lib/jvm/java-11-openjdk/jre/bin/java -Xmx512m -XX:MaxMetaspaceSize=64m -Dos.name=Linux Main
}
arg=$1
case "$arg" in
web_app)
run_web
;;
hello)
run_hello
;;
*)
show_usage
esac

@ -9,7 +9,8 @@ rm -rf occlum_context
mkdir occlum_context mkdir occlum_context
cd occlum_context cd occlum_context
occlum init occlum init
new_json="$(jq '.resource_limits.user_space_size = "320MB" | .process.default_mmap_size = "256MB"' Occlum.json)" && \ new_json="$(jq '.resource_limits.user_space_size = "320MB" |
.process.default_mmap_size = "256MB"' Occlum.json)" && \
echo "${new_json}" > Occlum.json echo "${new_json}" > Occlum.json
# 2. Copy files into Occlum Workspace and Build # 2. Copy files into Occlum Workspace and Build

@ -34,7 +34,10 @@ if [ ! -d "image/lib/python3.7" ];then
cp -f $alpine_fs/lib/libz.so.1 image/lib cp -f $alpine_fs/lib/libz.so.1 image/lib
cp -rf ../dataset image cp -rf ../dataset image
cp -f ../demo.py image cp -f ../demo.py image
new_json="$(jq '.resource_limits.user_space_size = "320MB" | .resource_limits.kernel_space_heap_size = "144MB" | .process.default_mmap_size = "256MB"' Occlum.json)" && echo "${new_json}" > Occlum.json new_json="$(jq '.resource_limits.user_space_size = "320MB" |
.resource_limits.kernel_space_heap_size = "144MB" |
.process.default_mmap_size = "256MB"' Occlum.json)" && \
echo "${new_json}" > Occlum.json
occlum build occlum build
fi fi

@ -107,6 +107,12 @@ RUN cd rust && ./build.sh && rm -rf /tmp/rust
ENV PATH="/opt/occlum/toolchains/rust/bin:$PATH" ENV PATH="/opt/occlum/toolchains/rust/bin:$PATH"
ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/opt/intel/sgxsdk/sdk_libs" ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/opt/intel/sgxsdk/sdk_libs"
# Install Occlum Java toolchain (JDK 11)
COPY toolchains/java /tmp/java
WORKDIR /tmp
RUN cd java && ./install.sh && rm -rf /tmp/java
ENV PATH="/opt/occlum/toolchains/jvm/bin:$PATH"
# Install the latest version of Occlum # Install the latest version of Occlum
WORKDIR /root WORKDIR /root
RUN git clone https://github.com/occlum/occlum && \ RUN git clone https://github.com/occlum/occlum && \

@ -94,6 +94,12 @@ RUN cd rust && ./build.sh && rm -rf /tmp/rust
ENV PATH="/opt/occlum/toolchains/rust/bin:$PATH" ENV PATH="/opt/occlum/toolchains/rust/bin:$PATH"
ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/opt/intel/sgxsdk/sdk_libs" ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/opt/intel/sgxsdk/sdk_libs"
# Install Occlum Java toolchain (JDK 11)
COPY toolchains/java /tmp/java
WORKDIR /tmp
RUN cd java && ./install.sh && rm -rf /tmp/java
ENV PATH="/opt/occlum/toolchains/jvm/bin:$PATH"
# Install the latest version of Occlum # Install the latest version of Occlum
WORKDIR /root WORKDIR /root
RUN git clone https://github.com/occlum/occlum && \ RUN git clone https://github.com/occlum/occlum && \

@ -0,0 +1,39 @@
From f195a65829b168efddad9cbe41b6154c4483005f Mon Sep 17 00:00:00 2001
From: "jeffery.wsj" <jeffery.wsj@alibaba-inc.com>
Date: Fri, 10 Jul 2020 08:31:42 +0000
Subject: [PATCH] Xhook SYS_getcpu vdso call
---
src/hotspot/os/linux/os_linux.cpp | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp
index dbf18b7b5f..59a2ef3ab6 100644
--- a/src/hotspot/os/linux/os_linux.cpp
+++ b/src/hotspot/os/linux/os_linux.cpp
@@ -2876,13 +2876,15 @@ int os::Linux::sched_getcpu_syscall(void) {
#elif defined(AMD64)
// Unfortunately we have to bring all these macros here from vsyscall.h
// to be able to compile on old linuxes.
- #define __NR_vgetcpu 2
- #define VSYSCALL_START (-10UL << 20)
- #define VSYSCALL_SIZE 1024
- #define VSYSCALL_ADDR(vsyscall_nr) (VSYSCALL_START+VSYSCALL_SIZE*(vsyscall_nr))
- typedef long (*vgetcpu_t)(unsigned int *cpu, unsigned int *node, unsigned long *tcache);
- vgetcpu_t vgetcpu = (vgetcpu_t)VSYSCALL_ADDR(__NR_vgetcpu);
- retval = vgetcpu(&cpu, NULL, NULL);
+// #define __NR_vgetcpu 2
+// #define VSYSCALL_START (-10UL << 20)
+// #define VSYSCALL_SIZE 1024
+// #define VSYSCALL_ADDR(vsyscall_nr) (VSYSCALL_START+VSYSCALL_SIZE*(vsyscall_nr))
+// typedef long (*vgetcpu_t)(unsigned int *cpu, unsigned int *node, unsigned long *tcache);
+// vgetcpu_t vgetcpu = (vgetcpu_t)VSYSCALL_ADDR(__NR_vgetcpu);
+// retval = vgetcpu(&cpu, NULL, NULL);
+ cpu = get_nprocs();
+ retval = 0;
#endif
return (retval == -1) ? retval : cpu;
--
2.17.1

@ -0,0 +1,40 @@
#!/bin/bash
THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
DOWNLOAD_DIR=/tmp/occlum_java_toolchain
INSTALL_DIR=/opt/occlum/toolchains/jvm
# Exit if any command fails
set -e
# Clean previous download and installation if any
rm -rf ${DOWNLOAD_DIR}
rm -rf ${INSTALL_DIR}
# Create the download directory
mkdir -p ${DOWNLOAD_DIR}
cd ${DOWNLOAD_DIR}
# Download and install JDK 11
JDK=openjdk-11-for-occlum-0.14.0
wget https://github.com/occlum/occlum/releases/download/0.14.0/${JDK}.tar.gz
tar -xf ${JDK}.tar.gz
mkdir -p ${INSTALL_DIR}/java-11-openjdk
mv ${DOWNLOAD_DIR}/${JDK} ${INSTALL_DIR}/java-11-openjdk/jre
# Clean the download directory
rm -rf ${DOWNLOAD_DIR}
# Generate the wrappers for executables
mkdir -p ${INSTALL_DIR}/bin
cat > ${INSTALL_DIR}/bin/occlum-java <<EOF
#!/bin/bash
LD_LIBRARY_PATH=/opt/occlum/toolchains/gcc/x86_64-linux-musl/lib ${INSTALL_DIR}/java-11-openjdk/jre/bin/java "\$@"
EOF
cat > ${INSTALL_DIR}/bin/occlum-javac <<EOF
#!/bin/bash
LD_LIBRARY_PATH=/opt/occlum/toolchains/gcc/x86_64-linux-musl/lib ${INSTALL_DIR}/java-11-openjdk/jre/bin/javac "\$@"
EOF
chmod +x ${INSTALL_DIR}/bin/occlum-java
chmod +x ${INSTALL_DIR}/bin/occlum-javac