You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@teaclave.apache.org by sh...@apache.org on 2022/11/11 05:18:07 UTC

[incubator-teaclave-java-tee-sdk] 27/48: [sdk] Add Embedded Libos tee enclave occlum for JavaEnclave

This is an automated email from the ASF dual-hosted git repository.

shaojunwang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave-java-tee-sdk.git

commit f2ebac3b8abeae9be73c6118bd6b066b8082ee77
Author: jeffery.wsj <je...@alibaba-inc.com>
AuthorDate: Tue Jun 28 10:48:51 2022 +0800

    [sdk] Add Embedded Libos tee enclave occlum for JavaEnclave
    
    Summary:
    1. Add occlum enclave for JavaEnclave as embedded mode
    2. Implement remote attestation generation and verification for Embedded LibOS enclave
    
    Test Plan: all tests pass
    
    Reviewers: lei.yul, cengfeng.lzy, sanhong.lsh
    
    Issue: https://aone.alibaba-inc.com/task/43348805
    
    CR: https://code.aone.alibaba-inc.com/java-tee/JavaEnclave/codereview/9413169
---
 build.sh                                           |   5 +-
 sdk/common/pom.xml                                 |   4 +
 .../EmbeddedLibOSInnerAttestationReport.java       |  40 ++++
 .../common/EnclaveInvocationContext.java           |   9 +-
 .../common/SocketEnclaveInvocationContext.java     |  51 +++++
 .../exception/ConfidentialComputingException.java  |   2 +
 .../enclave/NativeCommandUtil.java                 |   1 -
 .../enclave/agent/EnclaveAgent.java                | 102 +++++++++
 .../enclave/agent/EnclaveAgentServiceImpl.java     |  86 +++++++
 .../enclave/agent/EnclaveShutDown.java             |  49 ++++
 .../enclave/agent/RemoteAttestation.java           |  21 ++
 .../enclave/framework/LoadServiceInvoker.java      |   4 +-
 .../enclave/framework/ServiceMethodInvoker.java    |   1 -
 .../enclave/framework/UnloadServiceInvoker.java    |   1 -
 .../enclave/system/EnclavePhysicalMemory.java      |   1 -
 .../remote_attestation_generate/Makefile           |  14 ++
 .../jni_occlum_attestation_generate.c              |  83 +++++++
 .../jni_occlum_attestation_generate.h              |  47 ++++
 .../platform/tee_sdk_svm/wrapper/tee_sdk_wrapper.c |   1 -
 sdk/host/pom.xml                                   |   4 +
 .../host/AbstractEnclave.java                      |  34 +--
 .../host/AttestationReport.java                    |   3 +
 .../host/EmbeddedLibOSAttestationReport.java       |  10 +
 .../host/EmbeddedLibOSEnclave.java                 | 248 +++++++++++++++++++++
 .../host/EmbeddedLibOSEnclaveConfig.java           |  83 +++++++
 .../host/EnclaveConfigure.java                     |   5 +
 .../confidentialcomputing/host/EnclaveDebug.java   |   2 +-
 .../{EnclaveDebug.java => EnclaveSimulate.java}    |  14 +-
 .../confidentialcomputing/host/EnclaveType.java    |   7 +
 .../confidentialcomputing/host/ExtractLibrary.java |  79 ++++++-
 .../host/MockInJvmEnclave.java                     |   8 +-
 .../host/MockInSvmEnclave.java                     |  28 ++-
 .../host/ProxyEnclaveInvocationHandler.java        |  32 +--
 .../host/RemoteAttestation.java                    |   6 +-
 ...tationReport.java => SGXAttestationReport.java} |  20 +-
 .../host/SGXRemoteAttestationVerify.java           |   1 -
 .../host/TeeSdkAttestationReport.java              |  31 +--
 .../confidentialcomputing/host/TeeSdkEnclave.java  |  27 ++-
 .../host/exception/EnclaveCreatingException.java   |   1 +
 .../native/cpp/attestation_verify/sgx/jni/Makefile |   1 +
 .../sgx/jni/jni_remote_attestation_verify.c        |   1 -
 .../cpp/platform/libos_occlum_enclave/jni/Makefile |  13 ++
 .../libos_occlum_enclave/jni/jni_occlum_enclave.c  | 206 +++++++++++++++++
 .../libos_occlum_enclave/jni/jni_occlum_enclave.h  |  60 +++++
 .../cpp/platform/mock_in_svm/jni/jni_mock_in_svm.c |   7 +-
 .../cpp/platform/mock_in_svm/jni/jni_mock_in_svm.h |   6 +-
 .../cpp/platform/tee_sdk_svm/jni/jni_tee_sdk_svm.c |  17 +-
 .../cpp/platform/tee_sdk_svm/jni/jni_tee_sdk_svm.h |   6 +-
 .../host/MockTestEnclave.java                      |  24 +-
 .../host/TestRemoteAttestation.java                |  12 +-
 .../bin/platform/libos_occlum_enclave/jni/.gitkeep |   0
 .../libos_occlum_enclave_attestation/.gitkeep      |   0
 .../libos_occlum_enclave/enclave/config.mk         |   5 +
 .../platform/libos_occlum_enclave/jni/config.mk    |  17 ++
 .../config/platform/tee_sdk_svm/jni/config.mk      |   4 +-
 .../config/remote_attestation_verify/sgx/config.mk |   2 +-
 sdk/native/script/build_app/Makefile               |   5 +-
 .../script/build_app/libos_occlum_enclave_build.sh |  87 ++++++++
 sdk/native/script/build_app/make.sh                |   1 -
 sdk/native/script/build_enclave_sdk/Makefile       |   8 +
 sdk/native/script/build_host_sdk/Makefile          |  19 ++
 sdk/native/script/build_host_sdk/make.sh           |   7 +
 sdk/pom.xml                                        |  12 +-
 test/enclave/pom.xml                               |  21 +-
 .../src/main/resources/embedded_libos_enclave.json |  11 +
 test/host/pom.xml                                  |   4 +
 .../test/host/TestJavaEnclaveService.java          |  92 ++++++--
 test/pom.xml                                       |   2 +-
 tools/cicd/Dockerfile                              |  19 +-
 tools/cicd/make.sh                                 |   6 +-
 70 files changed, 1662 insertions(+), 178 deletions(-)

diff --git a/build.sh b/build.sh
index 5d096d2..fc270bc 100755
--- a/build.sh
+++ b/build.sh
@@ -9,6 +9,9 @@ SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
 
 cd "${SHELL_FOLDER}"
 
+# fix occlum aesm service issue.
+sed -i '128,129s/.*//g' /opt/occlum/build/bin/occlum
+
 # workspace dir is the same as build.sh path location.
 WORKDIR="$PWD"
 SETTING="--settings /root/tools/settings.xml"
@@ -19,4 +22,4 @@ cd "${WORKDIR}"/sdk && mvn $SETTING clean install
 rm -rf /opt/javaenclave && mkdir -p /opt/javaenclave && cp -r ${SHELL_FOLDER}/sdk/native/bin /opt/javaenclave \
 && cp -r ${SHELL_FOLDER}/sdk/native/config /opt/javaenclave && cp -r ${SHELL_FOLDER}/sdk/native/script/build_app /opt/javaenclave
 # Test unit test cases in JavaEnclave
-cd "${WORKDIR}"/test && mvn $SETTING -Pnative clean package
+cd "${WORKDIR}"/test && OCCLUM_RELEASE_ENCLAVE=true mvn $SETTING -Pnative clean package
diff --git a/sdk/common/pom.xml b/sdk/common/pom.xml
index b039d49..efe3fa5 100644
--- a/sdk/common/pom.xml
+++ b/sdk/common/pom.xml
@@ -80,6 +80,10 @@
         </plugins>
     </build>
     <dependencies>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-compress</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.jacoco</groupId>
             <artifactId>jacoco-maven-plugin</artifactId>
diff --git a/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EmbeddedLibOSInnerAttestationReport.java b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EmbeddedLibOSInnerAttestationReport.java
new file mode 100644
index 0000000..29e2c9f
--- /dev/null
+++ b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EmbeddedLibOSInnerAttestationReport.java
@@ -0,0 +1,40 @@
+package com.alibaba.confidentialcomputing.common;
+
+import java.io.Serializable;
+
+/**
+ * This class is used to transfer embedded lib os attestation report between JavaEnclave's
+ * host and enclave module.
+ */
+public final class EmbeddedLibOSInnerAttestationReport implements Serializable {
+    private static final long serialVersionUID = -6944029051086666440L;
+
+    private final byte[] quote;
+    private final byte[] mrSigner;
+    private final byte[] mrEnclave;
+    private final byte[] userData;
+
+
+    public EmbeddedLibOSInnerAttestationReport(byte[] quote, byte[] mrSigner, byte[] mrEnclave, byte[] userData) {
+        this.quote = quote;
+        this.mrSigner = mrSigner;
+        this.mrEnclave = mrEnclave;
+        this.userData = userData;
+    }
+
+    public byte[] getQuote() {
+        return this.quote;
+    }
+
+    public byte[] getMrSigner() {
+        return this.mrSigner;
+    }
+
+    public byte[] getMrEnclave() {
+        return this.mrEnclave;
+    }
+
+    public byte[] getUserData() {
+        return this.userData;
+    }
+}
diff --git a/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EnclaveInvocationContext.java b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EnclaveInvocationContext.java
index c0325a0..de7244f 100644
--- a/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EnclaveInvocationContext.java
+++ b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EnclaveInvocationContext.java
@@ -7,7 +7,7 @@ import java.io.Serializable;
  * call, including the service instance's unique instanceIdentity, interface name, class name,
  * method name and its parameters.
  */
-public final class EnclaveInvocationContext implements Serializable {
+public class EnclaveInvocationContext implements Serializable {
     private static final long serialVersionUID = 6878585714134748604L;
 
     private final ServiceHandler serviceHandler;
@@ -15,6 +15,13 @@ public final class EnclaveInvocationContext implements Serializable {
     private final String[] parameterTypes;
     private final Object[] arguments;
 
+    public EnclaveInvocationContext() {
+        this.serviceHandler = null;
+        this.methodName = null;
+        this.parameterTypes = null;
+        this.arguments = null;
+    }
+
     public EnclaveInvocationContext(ServiceHandler serviceHandler,
                                     String methodName,
                                     String[] parameterTypes,
diff --git a/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/SocketEnclaveInvocationContext.java b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/SocketEnclaveInvocationContext.java
new file mode 100644
index 0000000..93926b5
--- /dev/null
+++ b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/SocketEnclaveInvocationContext.java
@@ -0,0 +1,51 @@
+package com.alibaba.confidentialcomputing.common;
+
+/**
+ * This class stores a method's necessary information for reflection
+ * call by socket http, including the service instance's unique instanceIdentity,
+ * interface name, class name, method name and its parameters.
+ * It's used for embedded lib os inner service invocation.
+ */
+public final class SocketEnclaveInvocationContext extends EnclaveInvocationContext {
+    private static final long serialVersionUID = 6202620980098144988L;
+    public static final String SERVICE_LOADING = "service_loading";
+    public static final String SERVICE_UNLOADING = "service_unloading";
+    public static final String METHOD_INVOCATION = "method_invocation";
+    public static final String REMOTE_ATTESTATION_GENERATE = "remote_attestation_generate";
+    public static final String ENCLAVE_DESTROY = "enclave_destroy";
+
+    private final String agentServiceName;
+    private final byte[] userData;
+
+    public SocketEnclaveInvocationContext(
+            String agentServiceName,
+            EnclaveInvocationContext context) {
+        super(context.getServiceHandler(), context.getMethodName(), context.getParameterTypes(), context.getArguments());
+        this.agentServiceName = agentServiceName;
+        this.userData = null;
+    }
+
+    public SocketEnclaveInvocationContext(String agentServiceName, ServiceHandler serviceHandler) {
+        super(serviceHandler);
+        this.agentServiceName = agentServiceName;
+        this.userData = null;
+    }
+
+    public SocketEnclaveInvocationContext(String agentServiceName,  byte[] userData) {
+        this.agentServiceName = agentServiceName;
+        this.userData = userData;
+    }
+
+    public SocketEnclaveInvocationContext(String agentServiceName) {
+        this.agentServiceName = agentServiceName;
+        this.userData = null;
+    }
+
+    public String getAgentServiceName() {
+        return agentServiceName;
+    }
+
+    public byte[] getUserData() {
+        return userData;
+    }
+}
diff --git a/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/exception/ConfidentialComputingException.java b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/exception/ConfidentialComputingException.java
index 43c3b25..eaaba57 100644
--- a/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/exception/ConfidentialComputingException.java
+++ b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/exception/ConfidentialComputingException.java
@@ -9,6 +9,8 @@ public class ConfidentialComputingException extends Exception {
 
     private static final long serialVersionUID = 5964126736764332957L;
 
+    public ConfidentialComputingException() {super();}
+
     /**
      * @param info exception information.
      */
diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/NativeCommandUtil.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/NativeCommandUtil.java
index 9966a30..a5afe9f 100644
--- a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/NativeCommandUtil.java
+++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/NativeCommandUtil.java
@@ -3,7 +3,6 @@ package com.alibaba.confidentialcomputing.enclave;
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
-import java.io.SequenceInputStream;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
 import java.nio.file.Paths;
diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/EnclaveAgent.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/EnclaveAgent.java
new file mode 100644
index 0000000..3cf96df
--- /dev/null
+++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/EnclaveAgent.java
@@ -0,0 +1,102 @@
+package com.alibaba.confidentialcomputing.enclave.agent;
+
+import com.alibaba.confidentialcomputing.common.SerializationHelper;
+import com.alibaba.confidentialcomputing.common.SocketEnclaveInvocationContext;
+import com.alibaba.confidentialcomputing.common.exception.ConfidentialComputingException;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+
+class EnclaveAgent {
+    private static final String HTTP_EXECUTE_THREAD_NAME = "enclave_http_remote_invoking_thread";
+    private static final String HTTP_SERVER_NAME = "/enclaveAgent";
+    private static volatile EnclaveAgentServiceImpl service = new EnclaveAgentServiceImpl();
+    private static volatile HttpServer httpServer = null;
+
+    // socket service port is from host side.
+    public static void main(String[] args) throws ConfidentialComputingException, IOException {
+        if (args.length != 3) {
+            throw new ConfidentialComputingException("lib os enclave agent service's port resource is not available.");
+        }
+        int portHost = Integer.parseInt(args[0]);
+        int portEnclave = Integer.parseInt(args[1]);
+        int httpThreadPoolSize = Integer.parseInt(args[2]);
+
+        notifyHostAndCreateHttpConnect(portHost, portEnclave, httpThreadPoolSize);
+
+        // wait for enclave shut down notification.
+        EnclaveShutDown.shutDownWait();
+    }
+
+    private static void notifyHostAndCreateHttpConnect(int portHost, int portEnclave, int threadPoolSize) throws IOException {
+        // create http connection and wait for request from host.
+        httpServer = HttpServer.create(new InetSocketAddress(portEnclave), 0);
+        httpServer.createContext(HTTP_SERVER_NAME, new EnclaveHttpHandler());
+        httpServer.setExecutor(Executors.newScheduledThreadPool(threadPoolSize, new ThreadFactory() {
+            public Thread newThread(Runnable r) {
+                Thread thread = new Thread(r);
+                thread.setName(HTTP_EXECUTE_THREAD_NAME);
+                thread.setDaemon(true);
+                return thread;
+            }
+        }));
+        httpServer.start();
+        // notify host that enclave jvm had started up.
+        new Socket("localhost", portHost);
+    }
+
+    static void closeHttpService() {
+        httpServer.stop(0);
+    }
+
+    private static void writeBackResponse(HttpExchange exchange, byte[] response) throws IOException {
+        exchange.sendResponseHeaders(200, response.length);
+        OutputStream outputStream = exchange.getResponseBody();
+        outputStream.write(response);
+        outputStream.flush();
+        outputStream.close();
+    }
+
+    static class EnclaveHttpHandler implements HttpHandler {
+        @Override
+        public void handle(HttpExchange exchange) throws IOException {
+            InputStream inputStream = exchange.getRequestBody();
+            byte[] payload = inputStream.readAllBytes();
+            inputStream.close();
+            SocketEnclaveInvocationContext context = null;
+
+            try {
+                context = (SocketEnclaveInvocationContext) SerializationHelper.deserialize(payload);
+            } catch (ClassNotFoundException e) {
+                e.printStackTrace();
+            }
+
+            switch (context.getAgentServiceName()) {
+                case SocketEnclaveInvocationContext.SERVICE_LOADING:
+                    writeBackResponse(exchange, service.loadService(context.getServiceHandler().getServiceInterfaceName()));
+                    break;
+                case SocketEnclaveInvocationContext.SERVICE_UNLOADING:
+                    writeBackResponse(exchange, service.unloadService(context.getServiceHandler()));
+                    break;
+                case SocketEnclaveInvocationContext.METHOD_INVOCATION:
+                    writeBackResponse(exchange, service.invokeMethod(context));
+                    break;
+                case SocketEnclaveInvocationContext.REMOTE_ATTESTATION_GENERATE:
+                    writeBackResponse(exchange, service.generateAttestationReport(context.getUserData()));
+                    break;
+                case SocketEnclaveInvocationContext.ENCLAVE_DESTROY:
+                    writeBackResponse(exchange, service.destroy());
+                    break;
+                default:
+            }
+        }
+    }
+}
diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/EnclaveAgentServiceImpl.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/EnclaveAgentServiceImpl.java
new file mode 100644
index 0000000..b5e5716
--- /dev/null
+++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/EnclaveAgentServiceImpl.java
@@ -0,0 +1,86 @@
+package com.alibaba.confidentialcomputing.enclave.agent;
+
+import com.alibaba.confidentialcomputing.common.EnclaveInvocationContext;
+import com.alibaba.confidentialcomputing.common.EnclaveInvocationResult;
+import com.alibaba.confidentialcomputing.common.SerializationHelper;
+import com.alibaba.confidentialcomputing.common.ServiceHandler;
+import com.alibaba.confidentialcomputing.common.EmbeddedLibOSInnerAttestationReport;
+import com.alibaba.confidentialcomputing.common.exception.ConfidentialComputingException;
+import com.alibaba.confidentialcomputing.enclave.framework.LoadServiceInvoker;
+import com.alibaba.confidentialcomputing.enclave.framework.ServiceMethodInvoker;
+import com.alibaba.confidentialcomputing.enclave.framework.UnloadServiceInvoker;
+
+import java.io.IOException;
+
+public class EnclaveAgentServiceImpl {
+    private static final LoadServiceInvoker loadServiceInstance = new LoadServiceInvoker();
+    private static final ServiceMethodInvoker serviceInvokerInstance = new ServiceMethodInvoker();
+    private static final UnloadServiceInvoker unloadServiceInstance = new UnloadServiceInvoker();
+
+    protected EnclaveAgentServiceImpl() {
+    }
+
+    public byte[] loadService(String serviceName) {
+        try {
+            return SerializationHelper.serialize(loadServiceInstance.callMethod(serviceName));
+        } catch (IOException e) {
+            try {
+                return SerializationHelper.serialize(new EnclaveInvocationResult(null, e));
+            } catch (IOException ex) {
+            }
+        }
+        return null;
+    }
+
+    public byte[] unloadService(ServiceHandler handler) {
+        try {
+            return SerializationHelper.serialize(unloadServiceInstance.callMethod(handler));
+        } catch (IOException e) {
+            try {
+                return SerializationHelper.serialize(new EnclaveInvocationResult(null, e));
+            } catch (IOException ex) {
+            }
+        }
+        return null;
+    }
+
+    public byte[] invokeMethod(EnclaveInvocationContext context) {
+        try {
+            return SerializationHelper.serialize(serviceInvokerInstance.callMethod(context));
+        } catch (IOException e) {
+            try {
+                return SerializationHelper.serialize(new EnclaveInvocationResult(null, e));
+            } catch (IOException ex) {
+            }
+        }
+        return null;
+    }
+
+    public byte[] generateAttestationReport(byte[] userDate) {
+        EmbeddedLibOSInnerAttestationReport report = null;
+        Throwable exception = null;
+        try {
+            report = RemoteAttestation.generateAttestationReport(userDate);
+        } catch (ConfidentialComputingException e) {
+            exception = e;
+        }
+        try {
+            return SerializationHelper.serialize(new EnclaveInvocationResult(report, exception));
+        } catch (IOException e) {
+            try {
+                return SerializationHelper.serialize(new EnclaveInvocationResult(null, e));
+            } catch (IOException ex) {
+            }
+        }
+        return null;
+    }
+
+    public byte[] destroy() {
+        EnclaveShutDown.shutDownNotify();
+        try {
+            return SerializationHelper.serialize(new EnclaveInvocationResult(true, null));
+        } catch (IOException e) {
+        }
+        return null;
+    }
+}
diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/EnclaveShutDown.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/EnclaveShutDown.java
new file mode 100644
index 0000000..b448c9f
--- /dev/null
+++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/EnclaveShutDown.java
@@ -0,0 +1,49 @@
+package com.alibaba.confidentialcomputing.enclave.agent;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+class EnclaveShutDown {
+    private static final int SHUTDOWN_DELAY_DURATION = 1000; // TimeUnit.MilliSecond
+    private static BlockingQueue<Integer> queue = new LinkedBlockingQueue<>();
+
+    static void shutDownNotify() {
+        boolean interrupted = false;
+        try {
+            while (true) {
+                try {
+                    queue.put(0);
+                    return;
+                } catch (InterruptedException e) {
+                    interrupted = true;
+                }
+            }
+        } finally {
+            if (interrupted) {
+                Thread.currentThread().interrupt();
+            }
+        }
+    }
+
+    static void shutDownWait() {
+        boolean interrupted = false;
+        try {
+            while (true) {
+                try {
+                    queue.take();
+                    // wait for destroy localhost remote destroy invocation return.
+                    Thread.sleep(SHUTDOWN_DELAY_DURATION);
+                    // close cached socket resources and socket service.
+                    EnclaveAgent.closeHttpService();
+                    return;
+                } catch (InterruptedException e) {
+                    interrupted = true;
+                }
+            }
+        } finally {
+            if (interrupted) {
+                Thread.currentThread().interrupt();
+            }
+        }
+    }
+}
diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/RemoteAttestation.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/RemoteAttestation.java
new file mode 100644
index 0000000..557058c
--- /dev/null
+++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/RemoteAttestation.java
@@ -0,0 +1,21 @@
+package com.alibaba.confidentialcomputing.enclave.agent;
+
+import com.alibaba.confidentialcomputing.common.EmbeddedLibOSInnerAttestationReport;
+import com.alibaba.confidentialcomputing.common.exception.ConfidentialComputingException;
+
+public class RemoteAttestation {
+    // lib os embedded enclave remote attestation jni.so path in occlum image.
+    private final static String JNI_EXTRACTED_PACKAGE_PATH = "/usr/lib/libos_occlum_enclave_attestation/lib_occlum_attestation_generate.so";
+
+    private static native void registerNatives();
+    private static native EmbeddedLibOSInnerAttestationReport generateAttestationReportNative(byte[] userDate) throws ConfidentialComputingException;
+
+    static {
+        System.load(JNI_EXTRACTED_PACKAGE_PATH);
+        registerNatives();
+    }
+
+    public static EmbeddedLibOSInnerAttestationReport generateAttestationReport(byte[] userDate) throws ConfidentialComputingException {
+        return generateAttestationReportNative(userDate);
+    }
+}
diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/LoadServiceInvoker.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/LoadServiceInvoker.java
index d0c03ae..a4b2dec 100644
--- a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/LoadServiceInvoker.java
+++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/LoadServiceInvoker.java
@@ -17,9 +17,9 @@ public final class LoadServiceInvoker implements EnclaveMethodInvoker<String> {
         Class<?> service;
         try {
             service = Class.forName(inputData);
+            return new EnclaveInvocationResult(EnclaveContext.getInstance().loadService(service), null);
         } catch (ClassNotFoundException e) {
-            throw new RuntimeException("Can't find the service interface class.", e);
+            return new EnclaveInvocationResult(null, e);
         }
-        return new EnclaveInvocationResult(EnclaveContext.getInstance().loadService(service), null);
     }
 }
diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/ServiceMethodInvoker.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/ServiceMethodInvoker.java
index 8387804..7f12b9f 100644
--- a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/ServiceMethodInvoker.java
+++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/ServiceMethodInvoker.java
@@ -6,7 +6,6 @@ import com.alibaba.confidentialcomputing.common.ServiceHandler;
 import com.alibaba.confidentialcomputing.common.exception.ConfidentialComputingException;
 import jdk.vm.ci.meta.MetaUtil;
 
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Collections;
diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/UnloadServiceInvoker.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/UnloadServiceInvoker.java
index 5f5fb6b..0b82737 100644
--- a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/UnloadServiceInvoker.java
+++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/UnloadServiceInvoker.java
@@ -1,6 +1,5 @@
 package com.alibaba.confidentialcomputing.enclave.framework;
 
-
 import com.alibaba.confidentialcomputing.common.EnclaveInvocationResult;
 import com.alibaba.confidentialcomputing.common.ServiceHandler;
 import com.alibaba.confidentialcomputing.common.exception.ConfidentialComputingException;
diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/system/EnclavePhysicalMemory.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/system/EnclavePhysicalMemory.java
index 35521b5..cdab91d 100644
--- a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/system/EnclavePhysicalMemory.java
+++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/system/EnclavePhysicalMemory.java
@@ -6,7 +6,6 @@ import com.oracle.svm.core.util.VMError;
 import org.graalvm.word.UnsignedWord;
 import org.graalvm.word.WordFactory;
 
-import java.util.Properties;
 
 /**
  * Physical memory implementation for Enclave environment. The sysconf(_SC_PAGESIZE()) and
diff --git a/sdk/enclave/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate/Makefile b/sdk/enclave/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate/Makefile
new file mode 100644
index 0000000..cdf38d9
--- /dev/null
+++ b/sdk/enclave/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate/Makefile
@@ -0,0 +1,14 @@
+include $(NATIVE_BASE_DIR)/config/config.mk
+include $(NATIVE_BASE_DIR)/config/platform/libos_occlum_enclave/enclave/config.mk
+
+.PHONY: all build clean
+
+all: build
+
+build:
+	$(CC) jni_occlum_attestation_generate.c -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/$(shell uname -s | tr A-Z a-z) \
+	-I$(INCPATH) -I$(TEE_SDK_PATH)/include -L$(LIBPATH) -locclum_dcap -fPIC -shared \
+	-o $(BIN)/platform/libos_occlum_enclave/libos_occlum_enclave_attestation/lib_occlum_attestation_generate.so
+
+clean:
+	rm -rf $(BIN)/platform/libos_occlum_enclave/libos_occlum_enclave_attestation/lib_occlum_attestation_generate.so
\ No newline at end of file
diff --git a/sdk/enclave/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate/jni_occlum_attestation_generate.c b/sdk/enclave/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate/jni_occlum_attestation_generate.c
new file mode 100644
index 0000000..a9b689e
--- /dev/null
+++ b/sdk/enclave/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate/jni_occlum_attestation_generate.c
@@ -0,0 +1,83 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sgx_quote_3.h"
+#include "sgx_urts.h"
+#include "sgx_pce.h"
+#include "sgx_error.h"
+
+#include <occlum_dcap.h>
+
+#include "jni_occlum_attestation_generate.h"
+
+static JNINativeMethod embedded_libos_occlum_enclave_methods[] = {
+    {"generateAttestationReportNative",   LIBOS_OCCLUM_ENCLAVE_REMOTE_ATTESTATION_GENERATION_SIGNATURE,   (void *)&JavaEnclave_TeeLibOSNativeRemoteAttestationGenerate},
+};
+
+JNIEXPORT void JNICALL Java_com_alibaba_confidentialcomputing_enclave_agent_RemoteAttestation_registerNatives(JNIEnv *env, jclass cls) {
+    (*env)->RegisterNatives(env, cls, embedded_libos_occlum_enclave_methods, sizeof(embedded_libos_occlum_enclave_methods)/sizeof(embedded_libos_occlum_enclave_methods[0]));
+}
+
+JNIEXPORT jobject JNICALL JavaEnclave_TeeLibOSNativeRemoteAttestationGenerate(JNIEnv *env, jclass cls, jbyteArray userData) {
+
+    void *handle = dcap_quote_open();
+    if (handle == NULL) {
+        THROW_EXCEPTION(env, LIBOS_OCCLUM_ENCLAVE_REMOTE_ATTESTATION_EXCEPTION, "libos enclave occlum remote attestation generate: dcap_quote_open failed.")
+    }
+
+    uint32_t quote_size = dcap_get_quote_size(handle);
+    uint8_t *p_quote_buffer = (uint8_t*)malloc(quote_size);
+    if (p_quote_buffer == NULL) {
+        dcap_quote_close(handle);
+        THROW_EXCEPTION(env, LIBOS_OCCLUM_ENCLAVE_REMOTE_ATTESTATION_EXCEPTION, "libos enclave occlum remote attestation generate: malloc p_quote_buffer failed.")
+    }
+    memset(p_quote_buffer, 0, quote_size);
+
+    sgx_report_data_t report_data = {0};
+    jbyte *userData_copy = (*env)->GetByteArrayElements(env, userData, NULL);
+    int userData_copy_length = (*env)->GetArrayLength(env, userData);
+    memcpy(report_data.d, userData_copy, userData_copy_length);
+
+    int32_t ret = dcap_generate_quote(handle, p_quote_buffer, &report_data);
+    if (ret != 0x0) {
+        (*env)->ReleaseByteArrayElements(env, userData, userData_copy, 0);
+        free(p_quote_buffer);
+        dcap_quote_close(handle);
+        THROW_EXCEPTION(env, LIBOS_OCCLUM_ENCLAVE_REMOTE_ATTESTATION_EXCEPTION, "libos enclave occlum remote attestation generate: dcap_generate_quote failed.")
+    }
+
+    sgx_quote3_t *p_quote = (sgx_quote3_t *)p_quote_buffer;
+    sgx_report_body_t *p_rep_body = (sgx_report_body_t *)(&p_quote->report_body);
+
+    jbyteArray quote_array = (*env)->NewByteArray(env, quote_size);
+    jbyte *quote_array_ptr = (*env)->GetByteArrayElements(env, quote_array, NULL);
+    memcpy(quote_array_ptr, p_quote_buffer, quote_size);
+
+    // create mr enclave byte array.
+    jbyteArray mr_enclave = (*env)->NewByteArray(env, SGX_HASH_SIZE);
+    jbyte *mr_enclave_buf = (*env)->GetByteArrayElements(env, mr_enclave, NULL);
+    memcpy(mr_enclave_buf, p_quote->report_body.mr_enclave.m, SGX_HASH_SIZE);
+
+    // create mr signer byte array.
+    jbyteArray mr_signer = (*env)->NewByteArray(env, SGX_HASH_SIZE);
+    jbyte *mr_signer_buf = (*env)->GetByteArrayElements(env, mr_signer, NULL);
+    memcpy(mr_signer_buf, p_quote->report_body.mr_signer.m, SGX_HASH_SIZE);
+
+    // create user data byte array.
+    jbyteArray user_data = (*env)->NewByteArray(env, SGX_REPORT_DATA_SIZE);
+    jbyte *user_data_buf = (*env)->GetByteArrayElements(env, user_data, NULL);
+    memcpy(user_data_buf, p_quote->report_body.report_data.d, SGX_REPORT_DATA_SIZE);
+
+    (*env)->ReleaseByteArrayElements(env, userData, userData_copy, 0);
+    (*env)->ReleaseByteArrayElements(env, quote_array, quote_array_ptr, 0);
+    (*env)->ReleaseByteArrayElements(env, mr_enclave, mr_enclave_buf, 0);
+    (*env)->ReleaseByteArrayElements(env, mr_signer, mr_signer_buf, 0);
+    (*env)->ReleaseByteArrayElements(env, user_data, user_data_buf, 0);
+    free(p_quote_buffer);
+    dcap_quote_close(handle);
+
+    jclass libos_inner_ra_report_clazz = (*env)->FindClass(env, LIBOS_OCCLUM_INNER_ATTESTATION_REPORT);
+    jmethodID construct = (*env)->GetMethodID(env, libos_inner_ra_report_clazz, "<init>", "([B[B[B[B)V");
+    return (*env)->NewObject(env, libos_inner_ra_report_clazz, construct, quote_array, mr_signer, mr_enclave, user_data);
+}
diff --git a/sdk/enclave/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate/jni_occlum_attestation_generate.h b/sdk/enclave/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate/jni_occlum_attestation_generate.h
new file mode 100644
index 0000000..c88e9ed
--- /dev/null
+++ b/sdk/enclave/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate/jni_occlum_attestation_generate.h
@@ -0,0 +1,47 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_alibaba_confidentialcomputing_enclave_agent_RemoteAttestation */
+
+#ifndef _Included_com_alibaba_confidentialcomputing_enclave_agent_RemoteAttestation
+#define _Included_com_alibaba_confidentialcomputing_enclave_agent_RemoteAttestation
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LIBOS_OCCLUM_ENCLAVE_REMOTE_ATTESTATION_GENERATION_SIGNATURE  "([B)Lcom/alibaba/confidentialcomputing/common/EmbeddedLibOSInnerAttestationReport;"
+#define LIBOS_OCCLUM_INNER_ATTESTATION_REPORT                         "com/alibaba/confidentialcomputing/common/EmbeddedLibOSInnerAttestationReport"
+#define LIBOS_OCCLUM_ENCLAVE_REMOTE_ATTESTATION_EXCEPTION             "com.alibaba.confidentialcomputing.common.exception.ConfidentialComputingException"
+
+#define THROW_EXCEPTION(env, exception, info)                                  \
+{                                                                              \
+    jclass ra_class = (*env)->FindClass(env, exception);                       \
+    if (ra_class == NULL) {                                                    \
+        fprintf(stderr, "JavaEnclave Error:  ");                               \
+        fprintf(stderr, exception);                                            \
+        fprintf(stderr, " class loading failed.\n");                           \
+        return;                                                                \
+    }                                                                          \
+    (*env)->ThrowNew(env, ra_class, info);                                     \
+    return;                                                                    \
+}
+
+/*
+ * Class:     com_alibaba_confidentialcomputing_enclave_agent_RemoteAttestation
+ * Method:    registerNatives
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_alibaba_confidentialcomputing_enclave_agent_RemoteAttestation_registerNatives
+  (JNIEnv *, jclass);
+
+/*
+ * Class:     com_alibaba_confidentialcomputing_enclave_agent_RemoteAttestation
+ * Method:    generateAttestationReportNative
+ * Signature: ([B)Lcom/alibaba/confidentialcomputing/common/agent/EmbeddedLibOSInnerAttestationReport;
+ */
+JNIEXPORT jobject JNICALL JavaEnclave_TeeLibOSNativeRemoteAttestationGenerate
+  (JNIEnv *, jclass, jbyteArray);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
\ No newline at end of file
diff --git a/sdk/enclave/src/main/native/cpp/platform/tee_sdk_svm/wrapper/tee_sdk_wrapper.c b/sdk/enclave/src/main/native/cpp/platform/tee_sdk_svm/wrapper/tee_sdk_wrapper.c
index 95255d4..6d651ea 100644
--- a/sdk/enclave/src/main/native/cpp/platform/tee_sdk_svm/wrapper/tee_sdk_wrapper.c
+++ b/sdk/enclave/src/main/native/cpp/platform/tee_sdk_svm/wrapper/tee_sdk_wrapper.c
@@ -33,7 +33,6 @@ int tee_sdk_random(void* data, long size) {
 }
 
 int enclave_svm_isolate_create(void* isolate, void* isolateThread) {
-    // printf("JavaEnclave Warning: %s is called in enclave svm.\n", __FUNCTION__);
     graal_isolate_t* isolate_t;
     graal_isolatethread_t* thread_t;
 
diff --git a/sdk/host/pom.xml b/sdk/host/pom.xml
index 1a60a7a..c65e281 100644
--- a/sdk/host/pom.xml
+++ b/sdk/host/pom.xml
@@ -107,6 +107,10 @@
             <groupId>com.alibaba.confidentialcomputing</groupId>
             <artifactId>common</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.json</groupId>
+            <artifactId>json</artifactId>
+        </dependency>
         <dependency>
             <groupId>com.google.auto.service</groupId>
             <artifactId>auto-service-annotations</artifactId>
diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/AbstractEnclave.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/AbstractEnclave.java
index 486a59d..8b7bfe8 100644
--- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/AbstractEnclave.java
+++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/AbstractEnclave.java
@@ -17,7 +17,6 @@ import com.alibaba.confidentialcomputing.host.exception.RemoteAttestationExcepti
 import com.alibaba.confidentialcomputing.host.exception.ServicesLoadingException;
 import com.alibaba.confidentialcomputing.host.exception.ServicesUnloadingException;
 
-
 /**
  * AbstractEnclave implements all kinds of enclave platform's common operation.
  * Such as service loading、unloading and service method invocation.
@@ -33,6 +32,9 @@ abstract class AbstractEnclave implements Enclave {
         if (type == EnclaveType.TEE_SDK && mode == EnclaveDebug.NONE) {
             throw new EnclaveCreatingException("TEE SDK enclave's debug mode must be RELEASE or DEBUG.");
         }
+        if (type == EnclaveType.EMBEDDED_LIB_OS && mode == EnclaveDebug.NONE) {
+            throw new EnclaveCreatingException("EMBEDDED_LIB_OS enclave's debug mode must be RELEASE or DEBUG.");
+        }
         enclaveContext = new EnclaveContext(type, mode, recycler);
     }
 
@@ -44,11 +46,11 @@ abstract class AbstractEnclave implements Enclave {
         return enclaveContext;
     }
 
-    abstract byte[] loadServiceNative(byte[] payload) throws ServicesLoadingException;
+    abstract byte[] loadServiceNative(String service) throws ServicesLoadingException;
 
-    abstract byte[] unloadServiceNative(byte[] payload) throws ServicesUnloadingException;
+    abstract byte[] unloadServiceNative(ServiceHandler handler) throws ServicesUnloadingException;
 
-    abstract byte[] invokeMethodNative(byte[] payload) throws EnclaveMethodInvokingException;
+    abstract byte[] invokeMethodNative(EnclaveInvocationContext context) throws EnclaveMethodInvokingException;
 
     abstract AttestationReport generateAttestationReportNative(byte[] userData) throws RemoteAttestationException;
 
@@ -60,15 +62,9 @@ abstract class AbstractEnclave implements Enclave {
         try {
             // Only need to provide service's interface name is enough to load service
             // in enclave.
-            byte[] payload;
-            try {
-                payload = SerializationHelper.serialize(service.getName());
-            } catch (IOException e) {
-                throw new ServicesLoadingException("service name serialization failed.", e);
-            }
             EnclaveInvocationResult resultWrapper;
             try {
-                resultWrapper = (EnclaveInvocationResult) SerializationHelper.deserialize(loadServiceNative(payload));
+                resultWrapper = (EnclaveInvocationResult) SerializationHelper.deserialize(loadServiceNative(service.getName()));
             } catch (IOException | ClassNotFoundException e) {
                 throw new ServicesLoadingException("EnclaveInvokeResultWrapper deserialization failed.", e);
             }
@@ -98,15 +94,9 @@ abstract class AbstractEnclave implements Enclave {
             throw new ServicesUnloadingException("enclave was destroyed.");
         }
         try {
-            byte[] payload;
-            try {
-                payload = SerializationHelper.serialize(service);
-            } catch (IOException e) {
-                throw new ServicesUnloadingException("unload service serialization failed.", e);
-            }
             EnclaveInvocationResult resultWrapper;
             try {
-                resultWrapper = (EnclaveInvocationResult) SerializationHelper.deserialize(unloadServiceNative(payload));
+                resultWrapper = (EnclaveInvocationResult) SerializationHelper.deserialize(unloadServiceNative(service));
             } catch (IOException | ClassNotFoundException e) {
                 throw new ServicesUnloadingException("EnclaveInvokeResultWrapper deserialization failed.", e);
             }
@@ -125,15 +115,9 @@ abstract class AbstractEnclave implements Enclave {
             throw new EnclaveMethodInvokingException("enclave was destroyed.");
         }
         try {
-            byte[] payload;
-            try {
-                payload = SerializationHelper.serialize(input);
-            } catch (IOException e) {
-                throw new EnclaveMethodInvokingException("EnclaveInvokeMetaWrapper serialization failed.", e);
-            }
             EnclaveInvocationResult resultWrapper;
             try {
-                resultWrapper = (EnclaveInvocationResult) SerializationHelper.deserialize(invokeMethodNative(payload));
+                resultWrapper = (EnclaveInvocationResult) SerializationHelper.deserialize(invokeMethodNative(input));
             } catch (IOException | ClassNotFoundException e) {
                 throw new EnclaveMethodInvokingException("EnclaveInvokeResultWrapper deserialization failed.", e);
             }
diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/AttestationReport.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/AttestationReport.java
index dd8bcf9..9847907 100644
--- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/AttestationReport.java
+++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/AttestationReport.java
@@ -71,6 +71,9 @@ public class AttestationReport implements Serializable {
             case 3:
                 enclaveType = EnclaveType.TEE_SDK;
                 break;
+            case 4:
+                enclaveType = EnclaveType.EMBEDDED_LIB_OS;
+                break;
         }
         System.arraycopy(attestationReport, 1, report, 0, report.length);
         return new AttestationReport(enclaveType, report);
diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSAttestationReport.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSAttestationReport.java
new file mode 100644
index 0000000..1913119
--- /dev/null
+++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSAttestationReport.java
@@ -0,0 +1,10 @@
+package com.alibaba.confidentialcomputing.host;
+
+/**
+ * EmbeddedLibOSAttestationReport parse more details information from a lib os embedded type enclave's remote attestation report.
+ */
+public final class EmbeddedLibOSAttestationReport extends SGXAttestationReport {
+    EmbeddedLibOSAttestationReport(byte[] quote, byte[] mrSigner, byte[] mrEnclave, byte[] userData) {
+        super(EnclaveType.EMBEDDED_LIB_OS, quote, mrSigner, mrEnclave, userData);
+    }
+}
diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclave.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclave.java
new file mode 100644
index 0000000..a0c7ff2
--- /dev/null
+++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclave.java
@@ -0,0 +1,248 @@
+package com.alibaba.confidentialcomputing.host;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.*;
+import java.util.concurrent.*;
+
+import com.alibaba.confidentialcomputing.common.*;
+import com.alibaba.confidentialcomputing.host.exception.*;
+
+/**
+ * EmbeddedLibOSEnclave is a sgx2 enclave based on Ant's Occlum libos.
+ * EmbeddedLibOSEnclave is a singleton object module, there is only one
+ * EmbeddedLibOSEnclave object in a process.
+ */
+public class EmbeddedLibOSEnclave extends AbstractEnclave {
+    private static final int HTTP_CONNECT_TIMEOUT_MS = 50; // ms.
+    private static final int HTTP_READ_TIMEOUT_MS = 200;   // ms.
+    private static final int HTTP_READ_REMOTE_ATTESTATION_TIMEOUT_MS = HTTP_READ_TIMEOUT_MS * 10;  // ms.
+    private static final String EMBEDDED_LIB_OS_ENCLAVE_STARTUP_THREAD_NAME = "async_lib_os_enclave_startup_thread";
+    private static final String HTTP_SERVER_PREFIX = "http://localhost:";
+    private static final String HTTP_SERVER_NAME = "/enclaveAgent";
+    private final static String JNI_EXTRACTED_PACKAGE_PATH = "jni/lib_jni_embedded_lib_os_enclave.so";
+    private final static String EMBEDDED_LIB_OS_ENCLAVE_SIGNED_PACKAGE_PATH = "lib_embedded_lib_os_enclave_load.tgz";
+    private final static String EMBEDDED_LIB_OS_ENCLAVE_SIGNED_PACKAGE_PATH_TAIL = "occlum_instance";
+    private static volatile LibOSExtractTempPath extractTempPath;
+    private static volatile EmbeddedLibOSEnclave singleInstance;
+
+    // enclaveHandle stores created enclave's handle id.
+    private long enclaveHandle;
+    private int portHost;
+    private int portEnclave;
+    private URL url;
+    private String httpURL;
+
+    static EmbeddedLibOSEnclave getEmbeddedLibOSEnclaveInstance(EnclaveDebug mode, EnclaveSimulate sim) throws EnclaveCreatingException {
+        synchronized (EmbeddedLibOSEnclave.class) {
+            if (singleInstance == null) {
+                singleInstance = new EmbeddedLibOSEnclave(mode, sim);
+            }
+            return singleInstance;
+        }
+    }
+
+    private EmbeddedLibOSEnclave(EnclaveDebug mode, EnclaveSimulate sim) throws EnclaveCreatingException {
+        // Set EnclaveContext for this enclave instance.
+        super(EnclaveType.EMBEDDED_LIB_OS, mode, new EnclaveServicesRecycler());
+        // Extract jni .so and signed tee .so from .jar file.
+        // Only once extract and load operation.
+        if (extractTempPath == null) {
+            synchronized (EmbeddedLibOSEnclave.class) {
+                if (extractTempPath == null) {
+                    try {
+                        String jniTempFilePath = ExtractLibrary.extractLibrary(
+                                EmbeddedLibOSEnclave.class.getClassLoader(),
+                                JNI_EXTRACTED_PACKAGE_PATH);
+                        String embeddedLibOsSignedFilePath = ExtractLibrary.extractAndDeCompressTgz(
+                                EmbeddedLibOSEnclave.class.getClassLoader(),
+                                EMBEDDED_LIB_OS_ENCLAVE_SIGNED_PACKAGE_PATH) + "/" + EMBEDDED_LIB_OS_ENCLAVE_SIGNED_PACKAGE_PATH_TAIL;
+                        extractTempPath = new EmbeddedLibOSEnclave.LibOSExtractTempPath(jniTempFilePath, embeddedLibOsSignedFilePath);
+                        System.load(extractTempPath.getJniTempFilePath());
+                        registerNatives();
+                    } catch (IOException e) {
+                        throw new EnclaveCreatingException("extracting embedded lib os enclave jni .so or signed .so failed.", e);
+                    }
+                }
+            }
+        }
+
+        try {
+            portHost = getFreePort();
+            portEnclave = getFreePort();
+            httpURL = HTTP_SERVER_PREFIX + portEnclave + HTTP_SERVER_NAME;
+            url = new URL(httpURL);
+            // Attach to target enclave service by rmi.
+            attachToEnclaveAgent(mode, sim);
+        } catch (IOException e) {
+            throw new EnclaveCreatingException(e);
+        }
+    }
+
+    // apply a free port for localhost communication between host and enclave.
+    private int getFreePort() throws IOException {
+        try (ServerSocket serverSocket = new ServerSocket(0)) {
+            return serverSocket.getLocalPort();
+        }
+    }
+
+    private Future<EnclaveCreatingException> startupLibOSEnclaveAsync(EnclaveDebug mode, EnclaveSimulate sim) {
+        // Create embedded lib os enclave by native call asynchronously.
+        // Occlum embedded start up interface is occlum_pal_exec, it blocks until progress exit in enclave.
+        return Executors.newFixedThreadPool(1, new ThreadFactory() {
+            public Thread newThread(Runnable r) {
+                Thread thread = new Thread(r);
+                thread.setName(EMBEDDED_LIB_OS_ENCLAVE_STARTUP_THREAD_NAME);
+                thread.setDaemon(true);
+                return thread;
+            }
+        }).submit(() -> {
+            EnclaveCreatingException exception = null;
+            try {
+                nativeCreateEnclave(
+                        mode.getValue(),
+                        sim.getValue(),
+                        portHost,
+                        portEnclave,
+                        EmbeddedLibOSEnclaveConfig.getEmbeddedLibOSEnclaveConfigInstance(),
+                        extractTempPath.getLibOSSignedFilePath());
+            } catch (EnclaveCreatingException e) {
+                exception = e;
+            }
+            return exception;
+        });
+    }
+
+    // wait for enclave jvm start up and notify host.
+    private void waitForEnclaveStartup() throws IOException {
+        try (ServerSocket server = new ServerSocket(this.portHost)) {
+            server.setSoTimeout(EmbeddedLibOSEnclaveConfig.getEmbeddedLibOSEnclaveConfigInstance().getEmbeddedLibOSEnclaveStartupDuration());
+            server.accept();
+        }
+    }
+
+    // attach to enclave embedded lib os java service.
+    private void attachToEnclaveAgent(EnclaveDebug mode, EnclaveSimulate sim) throws EnclaveCreatingException {
+        startupLibOSEnclaveAsync(mode, sim);
+        try {
+            waitForEnclaveStartup();
+        } catch (IOException e) {
+            throw new EnclaveCreatingException(e);
+        }
+    }
+
+    private static native void registerNatives();
+
+    private native int nativeCreateEnclave(int mode, int sim, int portHost, int portEnclave, EmbeddedLibOSEnclaveConfig config, String path) throws EnclaveCreatingException;
+
+    private native int nativeDestroyEnclave(long enclaveHandler) throws EnclaveDestroyingException;
+
+    private byte[] remoteRequest(byte[] request, int connectTimeout, int inTimeout) throws IOException, InterruptedException {
+        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+        conn.setRequestMethod("POST");
+        conn.setRequestProperty("Connection", "Keep-Alive");
+        conn.setDoOutput(true);
+        conn.setDoInput(true);
+        conn.setConnectTimeout(connectTimeout);
+        conn.setReadTimeout(inTimeout);
+        conn.connect();
+
+        try (OutputStream outputStream = conn.getOutputStream()) {
+            outputStream.write(request);
+            outputStream.flush();
+        }
+
+        try (InputStream inputStream = conn.getInputStream()) {
+            return inputStream.readAllBytes();
+        }
+    }
+
+    @Override
+    byte[] loadServiceNative(String service) throws ServicesLoadingException {
+        try {
+            SocketEnclaveInvocationContext context =
+                    new SocketEnclaveInvocationContext(SocketEnclaveInvocationContext.SERVICE_LOADING, new ServiceHandler(service));
+            return remoteRequest(SerializationHelper.serialize(context), HTTP_CONNECT_TIMEOUT_MS, HTTP_READ_TIMEOUT_MS);
+        } catch (InterruptedException | IOException e) {
+            throw new ServicesLoadingException(e);
+        }
+    }
+
+    @Override
+    byte[] unloadServiceNative(ServiceHandler handler) throws ServicesUnloadingException {
+        try {
+            SocketEnclaveInvocationContext context =
+                    new SocketEnclaveInvocationContext(SocketEnclaveInvocationContext.SERVICE_UNLOADING, handler);
+            return remoteRequest(SerializationHelper.serialize(context), HTTP_CONNECT_TIMEOUT_MS, HTTP_READ_TIMEOUT_MS);
+        } catch (InterruptedException | IOException e) {
+            throw new ServicesUnloadingException(e);
+        }
+    }
+
+    @Override
+    byte[] invokeMethodNative(EnclaveInvocationContext service) throws EnclaveMethodInvokingException {
+        try {
+            SocketEnclaveInvocationContext context =
+                    new SocketEnclaveInvocationContext(SocketEnclaveInvocationContext.METHOD_INVOCATION, service);
+            // Should not set http timeout parameter in method invoke, the duration is deeply depends on user service.
+            return remoteRequest(SerializationHelper.serialize(context), HTTP_CONNECT_TIMEOUT_MS, 0x0);
+        } catch (InterruptedException | IOException e) {
+            throw new EnclaveMethodInvokingException(e);
+        }
+    }
+
+    @Override
+    AttestationReport generateAttestationReportNative(byte[] userData) throws RemoteAttestationException {
+        try {
+            SocketEnclaveInvocationContext context =
+                    new SocketEnclaveInvocationContext(SocketEnclaveInvocationContext.REMOTE_ATTESTATION_GENERATE, userData);
+            EnclaveInvocationResult resultWrapper = (EnclaveInvocationResult) SerializationHelper.deserialize(
+                    remoteRequest(SerializationHelper.serialize(context), HTTP_CONNECT_TIMEOUT_MS, HTTP_READ_REMOTE_ATTESTATION_TIMEOUT_MS));
+            if (resultWrapper.getException() != null) {
+                throw resultWrapper.getException();
+            }
+            EmbeddedLibOSInnerAttestationReport report = (EmbeddedLibOSInnerAttestationReport) resultWrapper.getResult();
+            return new EmbeddedLibOSAttestationReport(
+                    report.getQuote(),
+                    report.getMrSigner(),
+                    report.getMrEnclave(),
+                    report.getUserData());
+        } catch (InterruptedException | IOException | ClassNotFoundException e) {
+            throw new RemoteAttestationException(e);
+        } catch (Throwable e) {
+            throw new RemoteAttestationException(e);
+        }
+    }
+
+    static int verifyAttestationReport(byte[] quote) throws RemoteAttestationException {
+        return SGXRemoteAttestationVerify.VerifyAttestationReport(quote);
+    }
+
+    @Override
+    public void destroy() throws EnclaveDestroyingException {
+        synchronized (EmbeddedLibOSEnclave.class) {
+            // Because enclave libos occlum doesn't support creating a new occlum instance even
+            // destroy the pre-created occlum instance, Do nothing here.
+            // embedded lib os occlum instance in JavaEnclave is similar with a singleton instance.
+        }
+    }
+
+    class LibOSExtractTempPath {
+        private final String jniTempFilePath;
+        private final String libOsSignedFilePath;
+
+        LibOSExtractTempPath(String jniTempFilePath, String teeSdkSignedFilePath) {
+            this.jniTempFilePath = jniTempFilePath;
+            this.libOsSignedFilePath = teeSdkSignedFilePath;
+        }
+
+        String getJniTempFilePath() {
+            return jniTempFilePath;
+        }
+
+        String getLibOSSignedFilePath() {
+            return libOsSignedFilePath;
+        }
+    }
+}
diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclaveConfig.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclaveConfig.java
new file mode 100644
index 0000000..8eecb71
--- /dev/null
+++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclaveConfig.java
@@ -0,0 +1,83 @@
+package com.alibaba.confidentialcomputing.host;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import static com.alibaba.confidentialcomputing.host.ExtractLibrary.extractLibrary;
+
+class EmbeddedLibOSEnclaveConfig {
+    private final static String EMBEDDED_LIB_OS_ENCLAVE_CONFIG_FILE = "embedded_libos_enclave.json";
+    private static String configFilePath;
+    private static EmbeddedLibOSEnclaveConfig config;
+
+    private boolean debuggable = false;
+    private int agentHttpHandlerThreadPoolSize = 5;
+    private int embeddedLibOSEnclaveStartupDuration = (int) TimeUnit.MINUTES.toMillis(1);
+    private String libOSLogLevel = "off";
+    private String[] enclaveJVMArgs = null;
+
+    static {
+        try {
+            configFilePath = extractLibrary(EmbeddedLibOSEnclave.class.getClassLoader(), EMBEDDED_LIB_OS_ENCLAVE_CONFIG_FILE);
+            File file = new File(configFilePath);
+            String content = Files.readString(file.toPath(), Charset.forName("UTF-8"));
+            JSONObject jsonObject = new JSONObject(content);
+            boolean debuggable = jsonObject.getBoolean("debuggable");
+            int agentHttpHandlerThreadPoolSize = jsonObject.getInt("agent_http_handler_thread_pool_size");
+            int embeddedLibOSEnclaveStartupDuration = jsonObject.getInt("enclave_startup_duration_ms");
+            String libOSLogLevel = jsonObject.getString("log_level");
+            JSONArray jvmArgs = jsonObject.getJSONArray("enclave_jvm_args");
+            List<String> jvmArgsList = new ArrayList<>();
+            for (int i = 0; i < jvmArgs.length(); i++) {
+                jvmArgsList.add(jvmArgs.getString(i));
+            }
+            String[] enclaveJVMArgs = jvmArgsList.toArray(new String[jvmArgsList.size()]);
+            config = new EmbeddedLibOSEnclaveConfig(debuggable, agentHttpHandlerThreadPoolSize, embeddedLibOSEnclaveStartupDuration, libOSLogLevel, enclaveJVMArgs);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    static EmbeddedLibOSEnclaveConfig getEmbeddedLibOSEnclaveConfigInstance() {
+        return config;
+    }
+
+    private EmbeddedLibOSEnclaveConfig(boolean debuggable, int agentHttpHandlerThreadPoolSize, int embeddedLibOSEnclaveStartupDuration, String libOSLogLevel, String[] jvmArgs) {
+        this.debuggable = debuggable;
+        this.agentHttpHandlerThreadPoolSize = agentHttpHandlerThreadPoolSize;
+        this.embeddedLibOSEnclaveStartupDuration = embeddedLibOSEnclaveStartupDuration;
+        this.libOSLogLevel = libOSLogLevel;
+        this.enclaveJVMArgs = jvmArgs;
+    }
+
+    EnclaveDebug getDebuggable() {
+        if (this.debuggable) {
+            return EnclaveDebug.DEBUG;
+        }
+        return EnclaveDebug.RELEASE;
+    }
+
+    int getAgentHttpHandlerThreadPoolSize() {
+        return this.agentHttpHandlerThreadPoolSize;
+    }
+
+    int getEmbeddedLibOSEnclaveStartupDuration() {
+        return this.embeddedLibOSEnclaveStartupDuration;
+    }
+
+    String getLibOSLogLevel() {
+        return this.libOSLogLevel;
+    }
+
+    String[] getEnclaveJVMArgs() {
+        return this.enclaveJVMArgs;
+    }
+}
diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveConfigure.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveConfigure.java
index 208e4de..c958b4c 100644
--- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveConfigure.java
+++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveConfigure.java
@@ -25,6 +25,9 @@ class EnclaveConfigure {
                 case "TEE_SDK":
                     enclaveType = EnclaveType.TEE_SDK;
                     break;
+                case "EMBEDDED_LIB_OS":
+                    enclaveType = EnclaveType.EMBEDDED_LIB_OS;
+                    break;
                 case "MOCK_IN_JVM":
                     enclaveType = EnclaveType.MOCK_IN_JVM;
                     break;
@@ -77,6 +80,8 @@ class EnclaveConfigure {
                 return new MockInSvmEnclave();
             case TEE_SDK:
                 return new TeeSdkEnclave(enclaveDebug);
+            case EMBEDDED_LIB_OS:
+                return EmbeddedLibOSEnclave.getEmbeddedLibOSEnclaveInstance(EmbeddedLibOSEnclaveConfig.getEmbeddedLibOSEnclaveConfigInstance().getDebuggable(), EnclaveSimulate.HARDWARE);
             case NONE:
             default:
                 throw new EnclaveCreatingException("enclave type is not supported.");
diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveDebug.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveDebug.java
index bf8ab83..c0f2156 100644
--- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveDebug.java
+++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveDebug.java
@@ -3,7 +3,7 @@ package com.alibaba.confidentialcomputing.host;
 /**
  * An enumeration of enclave debug mode.
  */
-enum EnclaveDebug {
+public enum EnclaveDebug {
     /**
      * For MOCK_IN_JVM and MOCK_IN_SVM, there is no real enclave environment.
      */
diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveDebug.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveSimulate.java
similarity index 53%
copy from sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveDebug.java
copy to sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveSimulate.java
index bf8ab83..ce8b180 100644
--- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveDebug.java
+++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveSimulate.java
@@ -1,25 +1,25 @@
 package com.alibaba.confidentialcomputing.host;
 
 /**
- * An enumeration of enclave debug mode.
+ * An enumeration of enclave simulate mode.
  */
-enum EnclaveDebug {
+enum EnclaveSimulate {
     /**
      * For MOCK_IN_JVM and MOCK_IN_SVM, there is no real enclave environment.
      */
     NONE(0),
     /**
-     * TEE_SDK could debug by gdb tool in this mode.
+     * TEE_SDK/EMBEDDED_LIB_OS could run in simulate mode without sgx.
      */
-    DEBUG(1),
+    SIMULATE(1),
     /**
-     * TEE_SDK could not debug by gdb tool in this mode.
+     * TEE_SDK/EMBEDDED_LIB_OS could run in hardware mode with sgx.
      */
-    RELEASE(2);
+    HARDWARE(2);
 
     private final int value;
 
-    EnclaveDebug(int value) {
+    EnclaveSimulate(int value) {
         this.value = value;
     }
 
diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveType.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveType.java
index 8e7f098..45155c8 100644
--- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveType.java
+++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveType.java
@@ -23,4 +23,11 @@ public enum EnclaveType {
      * host application runs in jvm environment, and enclave package were loaded by host.
      */
     TEE_SDK,
+    /**
+     * An enclave based on Intel's SGX2, with OCCLUM Libos. Enclave application
+     * was compiled to .class files and packaged as a jar file, there is a jvm runs based
+     * on enclave's occlum libos. host application runs in jvm environment, and enclave
+     * package were loaded by host.
+     */
+    EMBEDDED_LIB_OS,
 }
\ No newline at end of file
diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ExtractLibrary.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ExtractLibrary.java
index 1ce65e0..890c624 100644
--- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ExtractLibrary.java
+++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ExtractLibrary.java
@@ -1,15 +1,19 @@
 package com.alibaba.confidentialcomputing.host;
 
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
+import org.apache.commons.compress.utils.IOUtils;
+
+import java.io.*;
+import java.util.zip.GZIPInputStream;
 
 /**
- * JavaEnclave building tool will put native .so files into a java .jar file,
- * ExtractLibrary will extracts tee sdk's jni .so and enclave signed .so into
- * a temp path from the jar file. it's very convenient for deployment.
+ * JavaEnclave building tool will put native .so files or .tgz files into a java .jar file,
+ * ExtractLibrary will extract tee sdk's jni .so and enclave signed .so into a temp path
+ * from the jar file.
+ * extractAndDeCompressTgz will extract embedded lib os enclave's compressed .tgz image and
+ * decompress .tgz file into target temp path from the jar file.
+ * it's very convenient for deployment.
  */
 public final class ExtractLibrary {
     /**
@@ -35,4 +39,63 @@ public final class ExtractLibrary {
         }
         return fullPath;
     }
+
+    /**
+     * get the temp file's full path.
+     *
+     * @param classLoader define the search scope for compressed fie .tgz.
+     * @param name        lib.tgz name in the jar file.
+     * @return the temp decompression file's full path.
+     */
+    public static String extractAndDeCompressTgz(ClassLoader classLoader, String name) throws IOException {
+        String fullPath = extractLibrary(classLoader, name);
+        String destDir = fullPath.replace(".tgz", "");
+        deCompressTgz(fullPath, destDir);
+        return destDir;
+    }
+
+    private static void deCompressTgz(String fullPath, String destDir) throws IOException {
+        TarArchiveEntry entry;
+        TarArchiveEntry[] subEntries;
+        File subEntryFile = null;
+        try (FileInputStream fis = new FileInputStream(fullPath);
+             GZIPInputStream gis = new GZIPInputStream(fis);
+             TarArchiveInputStream tis = new TarArchiveInputStream(gis)) {
+            while ((entry = tis.getNextTarEntry()) != null) {
+                StringBuilder entryFileName = new StringBuilder();
+                entryFileName.append(destDir).append(File.separator).append(entry.getName());
+                File entryFile = new File(entryFileName.toString());
+                if (entry.isDirectory()) {
+                    if (!entryFile.exists()) {
+                        entryFile.mkdir();
+                    }
+                    subEntries = entry.getDirectoryEntries();
+                    for (int i = 0; i < subEntries.length; i++) {
+                        try (OutputStream out = new FileOutputStream(subEntryFile)) {
+                            subEntryFile = new File(entryFileName + File.separator + subEntries[i].getName());
+                            IOUtils.copy(tis, out);
+                        }
+                    }
+                } else {
+                    checkFileExists(entryFile);
+                    OutputStream out = new FileOutputStream(entryFile);
+                    IOUtils.copy(tis, out);
+                    out.close();
+                }
+            }
+        }
+    }
+
+    private static void checkFileExists(File file) throws IOException {
+        if (file.isDirectory()) {
+            if (!file.exists()) {
+                file.mkdir();
+            }
+        } else {
+            if (file.getParentFile() != null && !file.getParentFile().exists()) {
+                file.getParentFile().mkdirs();
+            }
+            file.createNewFile();
+        }
+    }
 }
diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockInJvmEnclave.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockInJvmEnclave.java
index dc2e982..c25f114 100644
--- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockInJvmEnclave.java
+++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockInJvmEnclave.java
@@ -1,5 +1,7 @@
 package com.alibaba.confidentialcomputing.host;
 
+import com.alibaba.confidentialcomputing.common.EnclaveInvocationContext;
+import com.alibaba.confidentialcomputing.common.ServiceHandler;
 import com.alibaba.confidentialcomputing.host.exception.*;
 
 /**
@@ -22,17 +24,17 @@ class MockInJvmEnclave extends AbstractEnclave {
     }
 
     @Override
-    byte[] loadServiceNative(byte[] payload) throws ServicesLoadingException {
+    byte[] loadServiceNative(String service) throws ServicesLoadingException {
         return null;
     }
 
     @Override
-    byte[] unloadServiceNative(byte[] payload) throws ServicesUnloadingException {
+    byte[] unloadServiceNative(ServiceHandler handler) throws ServicesUnloadingException {
         return null;
     }
 
     @Override
-    byte[] invokeMethodNative(byte[] payload) throws EnclaveMethodInvokingException {
+    byte[] invokeMethodNative(EnclaveInvocationContext context) throws EnclaveMethodInvokingException {
         return null;
     }
 
diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockInSvmEnclave.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockInSvmEnclave.java
index d953afe..340553e 100644
--- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockInSvmEnclave.java
+++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockInSvmEnclave.java
@@ -1,7 +1,9 @@
 package com.alibaba.confidentialcomputing.host;
 
+import com.alibaba.confidentialcomputing.common.EnclaveInvocationContext;
+import com.alibaba.confidentialcomputing.common.SerializationHelper;
+import com.alibaba.confidentialcomputing.common.ServiceHandler;
 import com.alibaba.confidentialcomputing.host.exception.*;
-import com.alibaba.confidentialcomputing.host.exception.RemoteAttestationException;
 
 import java.io.IOException;
 
@@ -68,17 +70,35 @@ class MockInSvmEnclave extends AbstractEnclave {
     }
 
     @Override
-    byte[] loadServiceNative(byte[] payload) throws ServicesLoadingException {
+    byte[] loadServiceNative(String service) throws ServicesLoadingException {
+        byte[] payload;
+        try {
+            payload = SerializationHelper.serialize(service);
+        } catch (IOException e) {
+            throw new ServicesLoadingException("service name serialization failed.", e);
+        }
         return nativeLoadService(enclaveSvmSdkHandle, isolateHandle, payload);
     }
 
     @Override
-    byte[] unloadServiceNative(byte[] payload) throws ServicesUnloadingException {
+    byte[] unloadServiceNative(ServiceHandler handler) throws ServicesUnloadingException {
+        byte[] payload;
+        try {
+            payload = SerializationHelper.serialize(handler);
+        } catch (IOException e) {
+            throw new ServicesUnloadingException("unload service serialization failed.", e);
+        }
         return nativeUnloadService(enclaveSvmSdkHandle, isolateHandle, payload);
     }
 
     @Override
-    byte[] invokeMethodNative(byte[] payload) throws EnclaveMethodInvokingException {
+    byte[] invokeMethodNative(EnclaveInvocationContext context) throws EnclaveMethodInvokingException {
+        byte[] payload;
+        try {
+            payload = SerializationHelper.serialize(context);
+        } catch (IOException e) {
+            throw new EnclaveMethodInvokingException("EnclaveInvokeMetaWrapper serialization failed.", e);
+        }
         return nativeInvokeMethod(enclaveSvmSdkHandle, isolateHandle, payload);
     }
 
diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ProxyEnclaveInvocationHandler.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ProxyEnclaveInvocationHandler.java
index db1a6be..8666dcb 100644
--- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ProxyEnclaveInvocationHandler.java
+++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ProxyEnclaveInvocationHandler.java
@@ -50,21 +50,23 @@ class ProxyEnclaveInvocationHandler implements InvocationHandler, Runnable {
             result = enclave.InvokeEnclaveMethod(methodInvokeMetaWrapper);
         } catch (EnclaveMethodInvokingException e) {
             // Get cause exception if it has one.
-            ConfidentialComputingException enclaveException = (ConfidentialComputingException) e.getCause();
-            Throwable enclaveCauseException = enclaveException.getCause();
-            Class<?>[] exceptionTypes = method.getExceptionTypes();
-            if (enclaveCauseException instanceof InvocationTargetException) {
-                // Check whether cause exception matches one of the method's exception declaration.
-                // If it's true, it illustrates that an exception happened in enclave when the service
-                // method was invoked in enclave, we should throw this exception directly and user will
-                // handle it.
-                // If it's false, it illustrates that an exception happened in host side or enclave side,
-                // but the exception is not belong to the method's declaration. In the case we should throw
-                // EnclaveMethodInvokingException again.
-                Throwable rootCause = enclaveCauseException.getCause();
-                for (Class<?> exception : exceptionTypes) {
-                    if (exception == rootCause.getClass()) {
-                        throw rootCause;
+            Throwable causeException = e.getCause();
+            if (causeException instanceof ConfidentialComputingException) {
+                Throwable enclaveCauseException = causeException.getCause();
+                Class<?>[] exceptionTypes = method.getExceptionTypes();
+                if (enclaveCauseException instanceof InvocationTargetException) {
+                    // Check whether cause exception matches one of the method's exception declaration.
+                    // If it's true, it illustrates that an exception happened in enclave when the service
+                    // method was invoked in enclave, we should throw this exception directly and user will
+                    // handle it.
+                    // If it's false, it illustrates that an exception happened in host side or enclave side,
+                    // but the exception is not belong to the method's declaration. In the case we should throw
+                    // EnclaveMethodInvokingException again.
+                    Throwable rootCause = enclaveCauseException.getCause();
+                    for (Class<?> exception : exceptionTypes) {
+                        if (exception == rootCause.getClass()) {
+                            throw rootCause;
+                        }
                     }
                 }
             }
diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/RemoteAttestation.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/RemoteAttestation.java
index 239a35d..20255e6 100644
--- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/RemoteAttestation.java
+++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/RemoteAttestation.java
@@ -19,6 +19,8 @@ public final class RemoteAttestation {
             System.arraycopy(userData, 0, result, 0, userData.length);
         } else if (userData.length > 64) {
             throw new RemoteAttestationException("enclave remote attestation user data length exceeds 64 bytes.");
+        } else {
+            result = userData;
         }
         return result;
     }
@@ -59,8 +61,10 @@ public final class RemoteAttestation {
         switch (report.getEnclaveType()) {
             case TEE_SDK:
                 return TeeSdkEnclave.verifyAttestationReport(report.getQuote());
+            case EMBEDDED_LIB_OS:
+                return EmbeddedLibOSEnclave.verifyAttestationReport(report.getQuote());
             default:
-                throw new RemoteAttestationException("enclaveType must be TEE_SDK.");
+                throw new RemoteAttestationException("enclaveType must be TEE_SDK or EMBEDDED_LIB_OS.");
         }
     }
 }
diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkAttestationReport.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXAttestationReport.java
similarity index 56%
copy from sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkAttestationReport.java
copy to sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXAttestationReport.java
index 6ab0f44..3d66eae 100644
--- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkAttestationReport.java
+++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXAttestationReport.java
@@ -1,16 +1,28 @@
 package com.alibaba.confidentialcomputing.host;
 
 /**
- * TeeSdkAttestationReport parse more details information from a tee sdk type enclave's remote attestation report.
+ * SGX type enclave's remote attestation report.
  */
-public final class TeeSdkAttestationReport extends AttestationReport {
+public class SGXAttestationReport extends AttestationReport {
     private final byte[] mrSigner;
     private final byte[] mrEnclave;
+    private final byte[] userData;
 
-    TeeSdkAttestationReport(byte[] quote, byte[] mrSigner, byte[] mrEnclave) {
-        super(EnclaveType.TEE_SDK, quote);
+    SGXAttestationReport(EnclaveType type, byte[] quote, byte[] mrSigner, byte[] mrEnclave, byte[] userData) {
+        super(type, quote);
         this.mrSigner = mrSigner;
         this.mrEnclave = mrEnclave;
+        this.userData = userData;
+    }
+
+    /**
+     * Get enclave userData from an enclave's remote attestation report.
+     * <p>
+     *
+     * @return Remote attestation userData value which is from user.
+     */
+    public byte[] getUserData() {
+        return this.userData;
     }
 
     /**
diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXRemoteAttestationVerify.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXRemoteAttestationVerify.java
index c8c0343..2db853d 100644
--- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXRemoteAttestationVerify.java
+++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXRemoteAttestationVerify.java
@@ -1,6 +1,5 @@
 package com.alibaba.confidentialcomputing.host;
 
-import com.alibaba.confidentialcomputing.host.ExtractLibrary;
 import com.alibaba.confidentialcomputing.host.exception.RemoteAttestationException;
 
 import java.io.IOException;
diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkAttestationReport.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkAttestationReport.java
index 6ab0f44..4f75a2c 100644
--- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkAttestationReport.java
+++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkAttestationReport.java
@@ -3,33 +3,8 @@ package com.alibaba.confidentialcomputing.host;
 /**
  * TeeSdkAttestationReport parse more details information from a tee sdk type enclave's remote attestation report.
  */
-public final class TeeSdkAttestationReport extends AttestationReport {
-    private final byte[] mrSigner;
-    private final byte[] mrEnclave;
-
-    TeeSdkAttestationReport(byte[] quote, byte[] mrSigner, byte[] mrEnclave) {
-        super(EnclaveType.TEE_SDK, quote);
-        this.mrSigner = mrSigner;
-        this.mrEnclave = mrEnclave;
-    }
-
-    /**
-     * Get enclave measurementEnclave from an enclave's remote attestation report.
-     * <p>
-     *
-     * @return Remote attestation measurementEnclave value.
-     */
-    public byte[] getMeasurementEnclave() {
-        return this.mrEnclave;
-    }
-
-    /**
-     * Get enclave measurementSigner from an enclave's remote attestation report.
-     * <p>
-     *
-     * @return Remote attestation measurementSigner value.
-     */
-    public byte[] getMeasurementSigner() {
-        return this.mrSigner;
+public final class TeeSdkAttestationReport extends SGXAttestationReport {
+    TeeSdkAttestationReport(byte[] quote, byte[] mrSigner, byte[] mrEnclave, byte[] userData) {
+        super(EnclaveType.TEE_SDK, quote, mrSigner, mrEnclave, userData);
     }
 }
diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkEnclave.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkEnclave.java
index 50bd225..36052b5 100644
--- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkEnclave.java
+++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkEnclave.java
@@ -1,5 +1,8 @@
 package com.alibaba.confidentialcomputing.host;
 
+import com.alibaba.confidentialcomputing.common.EnclaveInvocationContext;
+import com.alibaba.confidentialcomputing.common.SerializationHelper;
+import com.alibaba.confidentialcomputing.common.ServiceHandler;
 import com.alibaba.confidentialcomputing.host.exception.*;
 
 import java.io.IOException;
@@ -75,17 +78,35 @@ class TeeSdkEnclave extends AbstractEnclave {
     }
 
     @Override
-    byte[] loadServiceNative(byte[] payload) throws ServicesLoadingException {
+    byte[] loadServiceNative(String service) throws ServicesLoadingException {
+        byte[] payload;
+        try {
+            payload = SerializationHelper.serialize(service);
+        } catch (IOException e) {
+            throw new ServicesLoadingException("service name serialization failed.", e);
+        }
         return nativeLoadService(enclaveHandle, isolateHandle, payload);
     }
 
     @Override
-    byte[] unloadServiceNative(byte[] payload) throws ServicesUnloadingException {
+    byte[] unloadServiceNative(ServiceHandler handler) throws ServicesUnloadingException {
+        byte[] payload;
+        try {
+            payload = SerializationHelper.serialize(handler);
+        } catch (IOException e) {
+            throw new ServicesUnloadingException("unload service serialization failed.", e);
+        }
         return nativeUnloadService(enclaveHandle, isolateHandle, payload);
     }
 
     @Override
-    byte[] invokeMethodNative(byte[] payload) throws EnclaveMethodInvokingException {
+    byte[] invokeMethodNative(EnclaveInvocationContext context) throws EnclaveMethodInvokingException {
+        byte[] payload;
+        try {
+            payload = SerializationHelper.serialize(context);
+        } catch (IOException e) {
+            throw new EnclaveMethodInvokingException("EnclaveInvokeMetaWrapper serialization failed.", e);
+        }
         return nativeInvokeMethod(enclaveHandle, isolateHandle, payload);
     }
 
diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/EnclaveCreatingException.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/EnclaveCreatingException.java
index 53307bd..44c4d6a 100644
--- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/EnclaveCreatingException.java
+++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/EnclaveCreatingException.java
@@ -8,6 +8,7 @@ import com.alibaba.confidentialcomputing.common.exception.ConfidentialComputingE
  * Programmers need to handle EnclaveCreatingException seriously.
  */
 public class EnclaveCreatingException extends ConfidentialComputingException {
+
     /**
      * @param info exception information.
      */
diff --git a/sdk/host/src/main/native/cpp/attestation_verify/sgx/jni/Makefile b/sdk/host/src/main/native/cpp/attestation_verify/sgx/jni/Makefile
index fda3ec9..a38e0b2 100644
--- a/sdk/host/src/main/native/cpp/attestation_verify/sgx/jni/Makefile
+++ b/sdk/host/src/main/native/cpp/attestation_verify/sgx/jni/Makefile
@@ -10,6 +10,7 @@ all: build
 build:
 	$(CC) -g -c -Wno-unused-parameter $(RA_VERIFY_INCDIR) -I$(JAVA_HOME)/lib -I$(JAVA_HOME)/include \
 	-I$(JAVA_HOME)/include/$(shell uname -s | tr A-Z a-z) -fPIC jni_remote_attestation_verify.c
+
 	$(CC) jni_remote_attestation_verify.o $(RA_VERIFY_LDFLAGS) -fPIC -shared -o $(BIN)/remote_attestation/sgx/jni/lib_jni_sgx_remote_attestation_verify.so
 
 clean:
diff --git a/sdk/host/src/main/native/cpp/attestation_verify/sgx/jni/jni_remote_attestation_verify.c b/sdk/host/src/main/native/cpp/attestation_verify/sgx/jni/jni_remote_attestation_verify.c
index fa53006..22b9478 100644
--- a/sdk/host/src/main/native/cpp/attestation_verify/sgx/jni/jni_remote_attestation_verify.c
+++ b/sdk/host/src/main/native/cpp/attestation_verify/sgx/jni/jni_remote_attestation_verify.c
@@ -65,7 +65,6 @@ verify_result_wrapper ecdsa_quote_verification_qvl(const uint8_t* quote, uint32_
 
     if (dcap_ret != SGX_QL_SUCCESS) {
         result.status = QUOTE_VERIFICATION_STATUS_QUOTE_VERIFY_FAILED;
-        // printf("JavaEnclave Remote Attestation Error: sgx_qv_verify_quote failed: 0x%04x\n", dcap_ret);
         return result;
     }
 
diff --git a/sdk/host/src/main/native/cpp/platform/libos_occlum_enclave/jni/Makefile b/sdk/host/src/main/native/cpp/platform/libos_occlum_enclave/jni/Makefile
new file mode 100644
index 0000000..cdd6548
--- /dev/null
+++ b/sdk/host/src/main/native/cpp/platform/libos_occlum_enclave/jni/Makefile
@@ -0,0 +1,13 @@
+include $(NATIVE_BASE_DIR)/config/config.mk
+include $(NATIVE_BASE_DIR)/config/platform/libos_occlum_enclave/jni/config.mk
+
+.PHONY: all build clean
+
+all: build
+
+build:
+	$(CC) $(C_FLAGS) -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/$(shell uname -s | tr A-Z a-z) -fPIC jni_occlum_enclave.c
+	$(CC) jni_occlum_enclave.o $(LINK_FLAGS) -fPIC -shared -o $(BIN)/platform/libos_occlum_enclave/jni/lib_jni_embedded_lib_os_enclave.so
+
+clean:
+	rm -rf *.o $(BIN)/platform/libos_occlum_enclave/jni/lib_jni_embedded_lib_os_enclave.so
\ No newline at end of file
diff --git a/sdk/host/src/main/native/cpp/platform/libos_occlum_enclave/jni/jni_occlum_enclave.c b/sdk/host/src/main/native/cpp/platform/libos_occlum_enclave/jni/jni_occlum_enclave.c
new file mode 100644
index 0000000..8099c79
--- /dev/null
+++ b/sdk/host/src/main/native/cpp/platform/libos_occlum_enclave/jni/jni_occlum_enclave.c
@@ -0,0 +1,206 @@
+#include <linux/limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <occlum_pal_api.h>
+
+#include "jni_occlum_enclave.h"
+
+#define OCCLUM_CMD_ARGS_MAX_LENGTH    50
+#define OCCLUM_HARDWARE_PAL_PATH      "/opt/occlum/build/lib/libocclum-pal.so"
+#define OCCLUM_SIMULATE_PAL_PATH      "/opt/occlum/build/lib/libocclum-pal_sim.so"
+#define OCCLUM_CMD_PATH               "/usr/lib/dragonwell11/jre/bin/java"
+#define OCCLUM_JVM_CMD_CP             "-cp"
+#define OCCLUM_JVM_CMD_JAR_PATH       "/usr/app/*"
+#define OCCLUM_JVM_CMD_MAIN_CLASS     "com.alibaba.confidentialcomputing.enclave.agent.EnclaveAgent"
+
+void set_long_field_value(JNIEnv *env, jclass class_mirror, jobject obj, const char *field_name, jlong value) {
+    jfieldID field_id = (*env)->GetFieldID(env, class_mirror, field_name, "J");
+    (*env)->SetLongField(env, obj, field_id, value);
+}
+
+jint parse_http_handler_thread_pool_size(JNIEnv *env, jobject config) {
+    jclass config_class = (*env)->GetObjectClass(env, config);
+    jmethodID get_thread_pool_id = (*env)->GetMethodID(env, config_class, "getAgentHttpHandlerThreadPoolSize", "()I");
+    return (*env)->CallObjectMethod(env, config, get_thread_pool_id);
+}
+
+jstring parse_log_level(JNIEnv *env, jobject config) {
+    jclass config_class = (*env)->GetObjectClass(env, config);
+    jmethodID get_log_level_id = (*env)->GetMethodID(env, config_class, "getLibOSLogLevel", "()Ljava/lang/String;");
+    return (*env)->CallObjectMethod(env, config, get_log_level_id);
+}
+
+jobjectArray parse_jvm_cmd_args(JNIEnv *env, jobject config) {
+    jclass config_class = (*env)->GetObjectClass(env, config);
+    jmethodID get_jvm_args_id = (*env)->GetMethodID(env, config_class, "getEnclaveJVMArgs", "()[Ljava/lang/String;");
+    return (*env)->CallObjectMethod(env, config, get_jvm_args_id);
+}
+
+static JNINativeMethod tee_lib_os_methods[] = {
+    {"nativeCreateEnclave",    ENCLAVE_CREATING_SIGNATURE,  (void *)&JavaEnclave_TeeLibOSNativeCreateEnclave},
+    {"nativeDestroyEnclave",   "(J)I",                      (void *)&JavaEnclave_TeeLibOSNativeDestroyEnclave},
+};
+
+JNIEXPORT void JNICALL
+Java_com_alibaba_confidentialcomputing_host_EmbeddedLibOSEnclave_registerNatives(JNIEnv *env, jclass cls) {
+    (*env)->RegisterNatives(env, cls, tee_lib_os_methods, sizeof(tee_lib_os_methods)/sizeof(tee_lib_os_methods[0]));
+}
+
+JNIEXPORT jint JNICALL JavaEnclave_TeeLibOSNativeCreateEnclave(JNIEnv *env, jobject obj, jint debug, jint sim, jint portHost, jint portEnclave, jobject config, jstring path) {
+    char* occlum_pal_path = OCCLUM_HARDWARE_PAL_PATH;
+    if (sim == 1) {
+        occlum_pal_path = OCCLUM_SIMULATE_PAL_PATH;
+    }
+
+    void *lib_occlum_pal_handle = dlopen(occlum_pal_path, RTLD_LOCAL | RTLD_LAZY);
+    if (!lib_occlum_pal_handle) {
+        THROW_EXCEPTION(env, ENCLAVE_CREATING_EXCEPTION, "create tee lib os enclave: dlopen occlum_pal_path.so failed.")
+    }
+
+    // set .so file handle back to java enclave object.
+    jclass class_enclave = (*env)->GetObjectClass(env, obj);
+    set_long_field_value(env, class_enclave, obj, "enclaveHandle", (jlong)lib_occlum_pal_handle);
+
+    // lookup symbol occlum_pal_init in libocclum-pal.so
+    int (*occlum_pal_init)(const struct occlum_pal_attr *attr);
+    occlum_pal_init = (int (*)(const struct occlum_pal_attr *))dlsym((void *)lib_occlum_pal_handle, "occlum_pal_init");
+    if (!occlum_pal_init) {
+        THROW_EXCEPTION(env, ENCLAVE_CREATING_EXCEPTION, "create tee lib os enclave: dlsym symbol occlum_pal_init failed.")
+    }
+
+    /* lookup symbol occlum_pal_create_process in libocclum-pal.so */
+    int (*occlum_pal_create_process)(struct occlum_pal_create_process_args *args);
+    occlum_pal_create_process = (int (*)(struct occlum_pal_create_process_args *))dlsym((void *)lib_occlum_pal_handle, "occlum_pal_create_process");
+    if (!occlum_pal_create_process) {
+        THROW_EXCEPTION(env, ENCLAVE_CREATING_EXCEPTION, "create tee lib os enclave: dlsym symbol occlum_pal_create_process failed.")
+    }
+
+    // lookup symbol occlum_pal_exec in libocclum-pal.so
+    int (*occlum_pal_exec)(struct occlum_pal_exec_args *args);
+    occlum_pal_exec = (int (*)(struct occlum_pal_exec_args *))dlsym((void *)lib_occlum_pal_handle, "occlum_pal_exec");
+    if (!occlum_pal_exec) {
+        THROW_EXCEPTION(env, ENCLAVE_CREATING_EXCEPTION, "create tee lib os enclave: dlsym symbol occlum_pal_exec failed.")
+    }
+
+    // parse occlum enclave log level.
+    jstring log_level = parse_log_level(env, config);
+    const char *log_level_str = (*env)->GetStringUTFChars(env, log_level, 0);
+    const char *path_str = (path == 0) ? 0 : (*env)->GetStringUTFChars(env, path, 0);
+    occlum_pal_attr_t pal_attr = OCCLUM_PAL_ATTR_INITVAL;
+    pal_attr.instance_dir = path_str;
+    pal_attr.log_level = log_level_str;
+    if (occlum_pal_init(&pal_attr) < 0) {
+        (*env)->ReleaseStringUTFChars(env, path, path_str);
+        (*env)->ReleaseStringUTFChars(env, log_level, log_level_str);
+        THROW_EXCEPTION(env, ENCLAVE_CREATING_EXCEPTION, "create tee lib os enclave: occlum_pal_init failed.")
+    }
+
+    const char *cmd_path = OCCLUM_CMD_PATH;
+    char *cmd_args[OCCLUM_CMD_ARGS_MAX_LENGTH] = {NULL};
+    t_jvm_args jvm_args_record[OCCLUM_CMD_ARGS_MAX_LENGTH] = {NULL};
+
+    // parse jvm args from user config file.
+    cmd_args[0] = cmd_path;
+    jobjectArray jvm_args = parse_jvm_cmd_args(env, config);
+    jsize length = (*env)->GetArrayLength(env, jvm_args);
+    if (length >= OCCLUM_CMD_ARGS_MAX_LENGTH) {
+        (*env)->ReleaseStringUTFChars(env, path, path_str);
+        (*env)->ReleaseStringUTFChars(env, log_level, log_level_str);
+        THROW_EXCEPTION(env, ENCLAVE_CREATING_EXCEPTION, "create tee lib os enclave: jvm args number exceeds max limitation 50.")
+    }
+
+    // parse jvm args and cache them in jvm_args_record for later release.
+    int index = 0x0;
+    for (; index < length; index++) {
+        jvm_args_record[index].handler = (jstring)(*env)->GetObjectArrayElement(env, jvm_args, index);
+        jvm_args_record[index].handler_str = (char *)(*env)->GetStringUTFChars(env, jvm_args_record[index].handler, 0);
+        cmd_args[1+index] = jvm_args_record[index].handler_str;
+    }
+    // add cp path, main class name in cmd_args's tail.
+    cmd_args[1+index++] = OCCLUM_JVM_CMD_CP;
+    cmd_args[1+index++] = OCCLUM_JVM_CMD_JAR_PATH;
+    cmd_args[1+index++] = OCCLUM_JVM_CMD_MAIN_CLASS;
+
+    // add portHost number as java args.
+    char port_host_buf[10];
+    sprintf(port_host_buf, "%d", portHost);
+    cmd_args[1+index++] = port_host_buf;
+
+    // add portEnclave number as java args.
+    char port_enclave_buf[10];
+    sprintf(port_enclave_buf, "%d", portEnclave);
+    cmd_args[1+index++] = port_enclave_buf;
+
+    // add http thread pool size as java args.
+    char thread_pool_size[10];
+    sprintf(thread_pool_size, "%d", parse_http_handler_thread_pool_size(env, config));
+    cmd_args[1+index] = thread_pool_size;
+
+    struct occlum_stdio_fds io_fds = {
+        .stdin_fd = STDIN_FILENO,
+        .stdout_fd = STDOUT_FILENO,
+        .stderr_fd = STDERR_FILENO,
+    };
+
+    // Use Occlum PAL to create new process
+    int libos_tid = 0;
+    struct occlum_pal_create_process_args create_process_args = {
+        .path = cmd_path,
+        .argv = cmd_args,
+        .env = NULL,
+        .stdio = (const struct occlum_stdio_fds *) &io_fds,
+        .pid = &libos_tid,
+    };
+    if (occlum_pal_create_process(&create_process_args) < 0) {
+        (*env)->ReleaseStringUTFChars(env, path, path_str);
+        (*env)->ReleaseStringUTFChars(env, log_level, log_level_str);
+        for (int i = 0x0; i < length; i++) {
+            (*env)->ReleaseStringUTFChars(env, jvm_args_record[i].handler, jvm_args_record[i].handler_str);
+        }
+        THROW_EXCEPTION(env, ENCLAVE_CREATING_EXCEPTION, "create tee lib os enclave: occlum_pal_create_process failed.")
+    }
+
+    // Use Occlum PAL to execute the cmd
+    int exit_status = 0;
+    struct occlum_pal_exec_args exec_args = {
+        .pid = libos_tid,
+        .exit_value = &exit_status,
+    };
+    // occlum_pal_exec will block until application run in occlum enclave exit.
+    if (occlum_pal_exec(&exec_args) < 0) {
+        (*env)->ReleaseStringUTFChars(env, path, path_str);
+        (*env)->ReleaseStringUTFChars(env, log_level, log_level_str);
+        for (int i = 0x0; i < length; i++) {
+            (*env)->ReleaseStringUTFChars(env, jvm_args_record[i].handler, jvm_args_record[i].handler_str);
+        }
+        THROW_EXCEPTION(env, ENCLAVE_CREATING_EXCEPTION, "create tee lib os enclave: occlum_pal_exec failed.")
+    }
+
+    (*env)->ReleaseStringUTFChars(env, path, path_str);
+    (*env)->ReleaseStringUTFChars(env, log_level, log_level_str);
+    for (int i = 0x0; i < length; i++) {
+        (*env)->ReleaseStringUTFChars(env, jvm_args_record[i].handler, jvm_args_record[i].handler_str);
+    }
+    return 0;
+}
+
+JNIEXPORT jint JNICALL JavaEnclave_TeeLibOSNativeDestroyEnclave(JNIEnv *env, jobject obj, jlong handler) {
+    // lookup symbol occlum_pal_destroy in libocclum-pal.so
+    int (*occlum_pal_destroy)(void);
+    occlum_pal_destroy = (int (*)(void))dlsym((void *)handler, "occlum_pal_destroy");
+
+    if (!occlum_pal_destroy) {
+        THROW_EXCEPTION(env, ENCLAVE_DESTROYING_EXCEPTION, "destroy tee lib os enclave: dlsym symbol occlum_pal_destroy failed.")
+    }
+
+    if (occlum_pal_destroy() != 0x0) {
+        THROW_EXCEPTION(env, ENCLAVE_DESTROYING_EXCEPTION, "destroy tee lib os enclave: occlum_pal_destroy failed.")
+    }
+
+    if (dlclose((void *)handler) != 0x0) {
+        THROW_EXCEPTION(env, ENCLAVE_DESTROYING_EXCEPTION, "destroy tee lib os enclave: close occlum_pal_path.so failed.")
+    }
+}
\ No newline at end of file
diff --git a/sdk/host/src/main/native/cpp/platform/libos_occlum_enclave/jni/jni_occlum_enclave.h b/sdk/host/src/main/native/cpp/platform/libos_occlum_enclave/jni/jni_occlum_enclave.h
new file mode 100644
index 0000000..c188536
--- /dev/null
+++ b/sdk/host/src/main/native/cpp/platform/libos_occlum_enclave/jni/jni_occlum_enclave.h
@@ -0,0 +1,60 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_alibaba_confidentialcomputing_host_EmbeddedLibOSEnclave */
+
+#ifndef _Included_com_alibaba_confidentialcomputing_host_EmbeddedLibOSEnclave
+#define _Included_com_alibaba_confidentialcomputing_host_EmbeddedLibOSEnclave
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ENCLAVE_CREATING_SIGNATURE         "(IIIILcom/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclaveConfig;Ljava/lang/String;)I"
+#define ENCLAVE_CREATING_EXCEPTION         "com/alibaba/confidentialcomputing/host/exception/EnclaveCreatingException"
+#define ENCLAVE_DESTROYING_EXCEPTION       "com/alibaba/confidentialcomputing/host/exception/EnclaveDestroyingException"
+
+typedef struct {
+    jstring  handler;
+    char*    handler_str;
+} t_jvm_args;
+
+#define THROW_EXCEPTION(env, exception, info)                                  \
+{                                                                              \
+    jclass ra_class = (*env)->FindClass(env, exception);                       \
+    if (ra_class == NULL) {                                                    \
+        fprintf(stderr, "JavaEnclave Error:  ");                               \
+        fprintf(stderr, exception);                                            \
+        fprintf(stderr, " class loading failed.\n");                           \
+        return;                                                                \
+    }                                                                          \
+    (*env)->ThrowNew(env, ra_class, info);                                     \
+    return;                                                                    \
+}
+
+/*
+ * Class:     com_alibaba_confidentialcomputing_host_EmbeddedLibOSEnclave
+ * Method:    registerNatives
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_alibaba_confidentialcomputing_host_EmbeddedLibOSEnclave_registerNatives
+  (JNIEnv *, jclass);
+
+/*
+ * Class:     com_alibaba_confidentialcomputing_host_EmbeddedLibOSEnclave
+ * Method:    nativeCreateEnclave
+ * Signature: (IIIILcom/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclaveConfig;Ljava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL JavaEnclave_TeeLibOSNativeCreateEnclave
+  (JNIEnv *, jobject, jint, jint, jint, jint, jobject, jstring);
+
+/*
+ * Class:     com_alibaba_confidentialcomputing_host_EmbeddedLibOSEnclave
+ * Method:    nativeDestroyEnclave
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL JavaEnclave_TeeLibOSNativeDestroyEnclave
+  (JNIEnv *, jobject, jlong);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
\ No newline at end of file
diff --git a/sdk/host/src/main/native/cpp/platform/mock_in_svm/jni/jni_mock_in_svm.c b/sdk/host/src/main/native/cpp/platform/mock_in_svm/jni/jni_mock_in_svm.c
index 32c189b..5510baa 100644
--- a/sdk/host/src/main/native/cpp/platform/mock_in_svm/jni/jni_mock_in_svm.c
+++ b/sdk/host/src/main/native/cpp/platform/mock_in_svm/jni/jni_mock_in_svm.c
@@ -134,7 +134,6 @@ JavaEnclave_MockSVMNativeSvmAttachIsolate(JNIEnv *env, jobject obj, jlong enclav
     }
 
     if (graal_create_isolate(NULL, &isolate_t, &isolate_thread_t) != 0) {
-        // fprintf(stderr, "graal_create_isolate create error:%s\n", dlerror());
         THROW_EXCEPTION(env, ENCLAVE_CREATING_EXCEPTION, "graal_create_isolate create error.")
     }
 
@@ -145,7 +144,7 @@ JavaEnclave_MockSVMNativeSvmAttachIsolate(JNIEnv *env, jobject obj, jlong enclav
     return 0;
 }
 
-JNIEXPORT jobject JNICALL
+JNIEXPORT jbyteArray JNICALL
 JavaEnclave_MockSVMNativeLoadService(JNIEnv *env, jobject obj, jlong enclave_handler, jlong isolate_handler, jbyteArray load_service_payload) {
     enclave_calling_stub_result result_wrapper =  mock_enclave_calling_entry(env, isolate_handler, load_service_payload, (mock_enclave_stub) mock_in_svm_load_service_symbol);
     if (result_wrapper.ret != 0) {
@@ -154,7 +153,7 @@ JavaEnclave_MockSVMNativeLoadService(JNIEnv *env, jobject obj, jlong enclave_han
     return result_wrapper.result;
 }
 
-JNIEXPORT jobject JNICALL
+JNIEXPORT jbyteArray JNICALL
 JavaEnclave_MockSVMNativeInvokeMethod(JNIEnv *env, jobject obj, jlong enclave_handler, jlong isolate_handler, jbyteArray invoke_payload) {
     enclave_calling_stub_result result_wrapper = mock_enclave_calling_entry(env, isolate_handler, invoke_payload, (mock_enclave_stub) mock_in_svm_invoke_service_symbol);
     if (result_wrapper.ret != 0) {
@@ -163,7 +162,7 @@ JavaEnclave_MockSVMNativeInvokeMethod(JNIEnv *env, jobject obj, jlong enclave_ha
     return result_wrapper.result;
 }
 
-JNIEXPORT jobject JNICALL
+JNIEXPORT jbyteArray JNICALL
 JavaEnclave_MockSVMNativeUnloadService(JNIEnv *env, jobject obj, jlong enclave_handler, jlong isolate_handler, jbyteArray unload_service_payload) {
     enclave_calling_stub_result result_wrapper = mock_enclave_calling_entry(env, isolate_handler, unload_service_payload, (mock_enclave_stub) mock_in_svm_unload_service_symbol);
     if (result_wrapper.ret != 0) {
diff --git a/sdk/host/src/main/native/cpp/platform/mock_in_svm/jni/jni_mock_in_svm.h b/sdk/host/src/main/native/cpp/platform/mock_in_svm/jni/jni_mock_in_svm.h
index 53db1a2..5449a51 100644
--- a/sdk/host/src/main/native/cpp/platform/mock_in_svm/jni/jni_mock_in_svm.h
+++ b/sdk/host/src/main/native/cpp/platform/mock_in_svm/jni/jni_mock_in_svm.h
@@ -21,9 +21,9 @@ typedef struct {
 {                                                                              \
     jclass ra_class = (*env)->FindClass(env, exception);                       \
     if (ra_class == NULL) {                                                    \
-        printf("JavaEnclave Error:  ");                                        \
-        printf(exception);                                                     \
-        printf(" class loading failed.\n");                                    \
+        fprintf(stderr, "JavaEnclave Error:  ");                               \
+        fprintf(stderr, exception);                                            \
+        fprintf(stderr, " class loading failed.\n");                           \
         return;                                                                \
     }                                                                          \
     (*env)->ThrowNew(env, ra_class, info);                                     \
diff --git a/sdk/host/src/main/native/cpp/platform/tee_sdk_svm/jni/jni_tee_sdk_svm.c b/sdk/host/src/main/native/cpp/platform/tee_sdk_svm/jni/jni_tee_sdk_svm.c
index 6a1870f..ad558d5 100644
--- a/sdk/host/src/main/native/cpp/platform/tee_sdk_svm/jni/jni_tee_sdk_svm.c
+++ b/sdk/host/src/main/native/cpp/platform/tee_sdk_svm/jni/jni_tee_sdk_svm.c
@@ -95,9 +95,7 @@ JavaEnclave_TeeSDKSVMNativeCreateEnclave(JNIEnv *env, jobject obj, jint mode, js
     const char *path_str = (path == 0) ? 0 : (*env)->GetStringUTFChars(env, path, 0);
     sgx_enclave_id_t enclave_id;
     int ret = sgx_create_enclave(path_str, enable_debug_mode, NULL, NULL, &enclave_id, NULL);
-
     (*env)->ReleaseStringUTFChars(env, path, path_str);
-
     if (ret != SGX_SUCCESS) {
         THROW_EXCEPTION(env, ENCLAVE_CREATING_EXCEPTION, "create tee sdk enclave by native calling failed.")
     }
@@ -158,12 +156,12 @@ JavaEnclave_TeeSDKSVMNativeUnloadService(JNIEnv *env, jobject obj, jlong enclave
 
 JNIEXPORT jint JNICALL
 JavaEnclave_TeeSDKSVMNativeSvmDetachIsolate(JNIEnv *env, jobject obj, jlong enclave_handler, jlong isolate_thread_handler) {
-    int ret = 0x0;
+    int ret = 0;
     enclave_svm_isolate_destroy((sgx_enclave_id_t)enclave_handler, &ret, (uint64_t)isolate_thread_handler);
     if (ret != 0) {
         THROW_EXCEPTION(env, ENCLAVE_DESTROYING_EXCEPTION, "isolate destroy native call failed.")
     }
-    return 0;
+    return ret;
 }
 
 JNIEXPORT jint JNICALL
@@ -177,7 +175,6 @@ JavaEnclave_TeeSDKSVMNativeDestroyEnclave(JNIEnv *env, jobject obj, jlong enclav
 JNIEXPORT jobject JNICALL
 JavaEnclave_TeeSDK_REMOTE_ATTESTATION_REPORT(JNIEnv *env, jobject obj, jlong enclave_handler, jbyteArray data) {
     int ret = 0;
-
     quote3_error_t qe3_ret = SGX_QL_SUCCESS;
     // Step one, load remote attestation related .signed files.
     if (SGX_QL_SUCCESS != (qe3_ret = load_qe_signed_package())) {
@@ -242,13 +239,19 @@ JavaEnclave_TeeSDK_REMOTE_ATTESTATION_REPORT(JNIEnv *env, jobject obj, jlong enc
     jbyte *mr_signer_buf = (*env)->GetByteArrayElements(env, mr_signer, NULL);
     memcpy(mr_signer_buf, ra_report.body.mr_signer.m, SGX_HASH_SIZE);
 
+    // create user data byte array.
+    jbyteArray user_data = (*env)->NewByteArray(env, SGX_REPORT_DATA_SIZE);
+    jbyte *user_data_buf = (*env)->GetByteArrayElements(env, user_data, NULL);
+    memcpy(user_data_buf, ra_report.body.report_data.d, SGX_REPORT_DATA_SIZE);
+
     (*env)->ReleaseByteArrayElements(env, data, data_copy, 0);
     (*env)->ReleaseByteArrayElements(env, quote_array, quote_array_ptr, 0);
     (*env)->ReleaseByteArrayElements(env, mr_enclave, mr_enclave_buf, 0);
     (*env)->ReleaseByteArrayElements(env, mr_signer, mr_signer_buf, 0);
+    (*env)->ReleaseByteArrayElements(env, user_data, user_data_buf, 0);
     free(quote_buffer_ptr);
 
     jclass tee_sdk_ra_report_clazz = (*env)->FindClass(env, TEE_SDK_REMOTE_ATTESTATION_REPORT_CLASS_NAME);
-    jmethodID construct = (*env)->GetMethodID(env, tee_sdk_ra_report_clazz, "<init>", "([B[B[B)V");
-    return (*env)->NewObject(env, tee_sdk_ra_report_clazz, construct, quote_array, mr_signer, mr_enclave);
+    jmethodID construct = (*env)->GetMethodID(env, tee_sdk_ra_report_clazz, "<init>", "([B[B[B[B)V");
+    return (*env)->NewObject(env, tee_sdk_ra_report_clazz, construct, quote_array, mr_signer, mr_enclave, user_data);
 }
\ No newline at end of file
diff --git a/sdk/host/src/main/native/cpp/platform/tee_sdk_svm/jni/jni_tee_sdk_svm.h b/sdk/host/src/main/native/cpp/platform/tee_sdk_svm/jni/jni_tee_sdk_svm.h
index 561b448..2dfced4 100644
--- a/sdk/host/src/main/native/cpp/platform/tee_sdk_svm/jni/jni_tee_sdk_svm.h
+++ b/sdk/host/src/main/native/cpp/platform/tee_sdk_svm/jni/jni_tee_sdk_svm.h
@@ -27,9 +27,9 @@ typedef struct {
 {                                                                              \
     jclass ra_class = (*env)->FindClass(env, exception);                       \
     if (ra_class == NULL) {                                                    \
-        printf("JavaEnclave Error:  ");                                        \
-        printf(exception);                                                     \
-        printf(" class loading failed.\n");                                    \
+        fprintf(stderr, "JavaEnclave Error:  ");                               \
+        fprintf(stderr, exception);                                            \
+        fprintf(stderr, " class loading failed.\n");                           \
         return;                                                                \
     }                                                                          \
     (*env)->ThrowNew(env, ra_class, info);                                     \
diff --git a/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/MockTestEnclave.java b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/MockTestEnclave.java
index 90df27e..e659c99 100644
--- a/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/MockTestEnclave.java
+++ b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/MockTestEnclave.java
@@ -12,7 +12,6 @@ import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
 
-
 class MockTestEnclave extends AbstractEnclave {
     private static final AtomicLong instanceIdentity = new AtomicLong(0);
     private static final Map<String, Object> instancesRegisterCenter = new ConcurrentHashMap<>();
@@ -73,12 +72,11 @@ class MockTestEnclave extends AbstractEnclave {
     }
 
     @Override
-    byte[] loadServiceNative(byte[] payload) throws ServicesLoadingException {
+    byte[] loadServiceNative(String interfaceName) throws ServicesLoadingException {
         List<ServiceHandler> handlers = new ArrayList<>();
         Throwable exception = null;
         EnclaveInvocationResult result;
         try {
-            String interfaceName = (String) SerializationHelper.deserialize(payload);
             Class<?> service = Class.forName(interfaceName);
             Iterator<?> services = ServiceLoader.load(service).iterator();
             while (services.hasNext()) {
@@ -89,7 +87,7 @@ class MockTestEnclave extends AbstractEnclave {
                 cacheServiceHandler.add(sm);
                 instancesRegisterCenter.put(identity, instance);
             }
-        } catch (IOException | ClassNotFoundException e) {
+        } catch (ClassNotFoundException e) {
             exception = e;
         } finally {
             result = new EnclaveInvocationResult(handlers.toArray(new ServiceHandler[0]), exception);
@@ -103,18 +101,12 @@ class MockTestEnclave extends AbstractEnclave {
     }
 
     @Override
-    byte[] unloadServiceNative(byte[] payload) throws ServicesUnloadingException {
-        ServiceHandler serviceHandler;
+    byte[] unloadServiceNative(ServiceHandler handler) throws ServicesUnloadingException {
         Throwable exception = null;
         EnclaveInvocationResult result;
-        try {
-            serviceHandler = (ServiceHandler) SerializationHelper.deserialize(payload);
-            instancesRegisterCenter.remove(serviceHandler.getInstanceIdentity());
-        } catch (IOException | ClassNotFoundException e) {
-            exception = e;
-        } finally {
-            result = new EnclaveInvocationResult(null, exception);
-        }
+
+        instancesRegisterCenter.remove(handler.getInstanceIdentity());
+        result = new EnclaveInvocationResult(null, exception);
 
         try {
             return SerializationHelper.serialize(result);
@@ -124,13 +116,11 @@ class MockTestEnclave extends AbstractEnclave {
     }
 
     @Override
-    byte[] invokeMethodNative(byte[] payload) throws EnclaveMethodInvokingException {
-        EnclaveInvocationContext invocationContext;
+    byte[] invokeMethodNative(EnclaveInvocationContext invocationContext) throws EnclaveMethodInvokingException {
         Throwable exception = null;
         Object invokeRet = null;
         EnclaveInvocationResult result;
         try {
-            invocationContext = (EnclaveInvocationContext) SerializationHelper.deserialize(payload);
             String className = invocationContext.getServiceHandler().getServiceImplClassName();
             String[] parameterTypes = invocationContext.getParameterTypes();
             String methodName = invocationContext.getMethodName();
diff --git a/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/TestRemoteAttestation.java b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/TestRemoteAttestation.java
index d4b9a20..8f161c4 100644
--- a/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/TestRemoteAttestation.java
+++ b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/TestRemoteAttestation.java
@@ -11,7 +11,7 @@ import static org.junit.jupiter.api.Assertions.*;
 
 class TestRemoteAttestation {
     @Test
-    void testRemoteAttestation() throws EnclaveCreatingException {
+    void testRemoteAttestation() {
         Enclave mockInJvmEnclave = new MockInJvmEnclave();
         assertThrows(RemoteAttestationException.class, () -> RemoteAttestation.generateAttestationReport(mockInJvmEnclave, null));
         assertThrows(RemoteAttestationException.class, () -> RemoteAttestation.verifyAttestationReport(new AttestationReport(EnclaveType.MOCK_IN_JVM, null)));
@@ -37,7 +37,7 @@ class TestRemoteAttestation {
     }
 
     @Test
-    void testAttestationReport() throws Exception {
+    void testAttestationReport() {
         byte[] quote = new byte[4];
         for (int index = 0; index < quote.length; index++) {
             quote[index] = (byte) 0x5f;
@@ -49,5 +49,13 @@ class TestRemoteAttestation {
         for (int index = 0; index < quote.length; index++) {
             assertEquals(quote[index], (deserializedReport.getQuote())[index]);
         }
+
+        report = new AttestationReport(EnclaveType.EMBEDDED_LIB_OS, quote);
+        serializedReport = report.toByteArray();
+        deserializedReport = AttestationReport.fromByteArray(serializedReport);
+        assertEquals(EnclaveType.EMBEDDED_LIB_OS, deserializedReport.getEnclaveType());
+        for (int index = 0; index < quote.length; index++) {
+            assertEquals(quote[index], (deserializedReport.getQuote())[index]);
+        }
     }
 }
diff --git a/sdk/native/bin/platform/libos_occlum_enclave/jni/.gitkeep b/sdk/native/bin/platform/libos_occlum_enclave/jni/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/sdk/native/bin/platform/libos_occlum_enclave/libos_occlum_enclave_attestation/.gitkeep b/sdk/native/bin/platform/libos_occlum_enclave/libos_occlum_enclave_attestation/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/sdk/native/config/platform/libos_occlum_enclave/enclave/config.mk b/sdk/native/config/platform/libos_occlum_enclave/enclave/config.mk
new file mode 100644
index 0000000..941f478
--- /dev/null
+++ b/sdk/native/config/platform/libos_occlum_enclave/enclave/config.mk
@@ -0,0 +1,5 @@
+CC := /usr/local/occlum/bin/occlum-gcc
+
+TEE_SDK_PATH = /opt/teesdk/sgxsdk
+LIBPATH ?= /opt/occlum/toolchains/dcap_lib/musl
+INCPATH ?= /opt/occlum/toolchains/dcap_lib/inc
diff --git a/sdk/native/config/platform/libos_occlum_enclave/jni/config.mk b/sdk/native/config/platform/libos_occlum_enclave/jni/config.mk
new file mode 100644
index 0000000..c29f118
--- /dev/null
+++ b/sdk/native/config/platform/libos_occlum_enclave/jni/config.mk
@@ -0,0 +1,17 @@
+CC := gcc
+OCCLUM_PREFIX ?= /opt/occlum
+SGX_MODE ?= HW
+
+ifneq ($(SGX_MODE), HW)
+	URTS_LIBRARY_NAME := sgx_urts_sim
+	UAE_SERVICE_LIBRARY_NAME := sgx_uae_service_sim
+	OCCLUM_PAL_LIB := occlum-pal_sim
+else
+	URTS_LIBRARY_NAME := sgx_urts
+	UAE_SERVICE_LIBRARY_NAME := sgx_uae_service
+	OCCLUM_PAL_LIB := occlum-pal
+endif
+
+C_FLAGS := -Wl,-z,noexecstack -g -c -Wno-unused-parameter -I$(OCCLUM_PREFIX)/include
+
+LINK_FLAGS := -lpthread -L$(OCCLUM_PREFIX)/build/lib -L/opt/teesdk/sgxsdk/lib64 -l$(URTS_LIBRARY_NAME) -l$(UAE_SERVICE_LIBRARY_NAME) -lsgx_uprotected_fs
\ No newline at end of file
diff --git a/sdk/native/config/platform/tee_sdk_svm/jni/config.mk b/sdk/native/config/platform/tee_sdk_svm/jni/config.mk
index f54e623..76bc3bc 100644
--- a/sdk/native/config/platform/tee_sdk_svm/jni/config.mk
+++ b/sdk/native/config/platform/tee_sdk_svm/jni/config.mk
@@ -4,9 +4,9 @@ CXX = g++
 TEE_SDK_PATH = /opt/teesdk/sgxsdk
 UBUNTU_OS = $(shell if [ -d "/usr/lib/x86_64-linux-gnu" ]; then echo "yes"; else echo "no"; fi;)
 ifeq ("$(UBUNTU_OS)", "yes")
-    DCAP_LIB_PATH = /usr/lib/x86_64-linux-gnu
+	DCAP_LIB_PATH = /usr/lib/x86_64-linux-gnu
 else
-    DCAP_LIB_PATH = /usr/lib64
+	DCAP_LIB_PATH = /usr/lib64
 endif
 
 # SGX_MODE ?= SIM
diff --git a/sdk/native/config/remote_attestation_verify/sgx/config.mk b/sdk/native/config/remote_attestation_verify/sgx/config.mk
index 032c4fb..2783eff 100644
--- a/sdk/native/config/remote_attestation_verify/sgx/config.mk
+++ b/sdk/native/config/remote_attestation_verify/sgx/config.mk
@@ -10,4 +10,4 @@ else
 endif
 
 RA_VERIFY_INCDIR = -I$(TEE_SDK_PATH)/include
-RA_VERIFY_LDFLAGS = -L$(DCAP_LIB_PATH) -lsgx_dcap_quoteverify -lsgx_dcap_ql
\ No newline at end of file
+RA_VERIFY_LDFLAGS = -L$(DCAP_LIB_PATH) -lsgx_dcap_quoteverify -lsgx_dcap_ql
diff --git a/sdk/native/script/build_app/Makefile b/sdk/native/script/build_app/Makefile
index 85d3a30..ec3d6c0 100644
--- a/sdk/native/script/build_app/Makefile
+++ b/sdk/native/script/build_app/Makefile
@@ -24,7 +24,6 @@ ifeq ($(TEE_SDK), TRUE)
 	-fpie -ljava -lzip -lnio -lnet -ljvm -lfdlibm -llibchelper \
 	$(TS_ENCLAVE_LDFLAGS) -Wl,--version-script=/opt/javaenclave/config/platform/tee_sdk_svm/edl/tee_sdk_enclave.lds
 
-    # sign the enclave image
     ifeq ($(ENCLAVE_PRIVATE_PEM_PATH), )
 		openssl genrsa -out ${ENCLAVE_BASE_DIR}/target/enclave_workspace/private.pem -3 3072
 		$(SGX_ENCLAVE_SIGNER) sign -enclave ${ENCLAVE_BASE_DIR}/target/svm-output/lib_tee_sdk_svm_load \
@@ -36,3 +35,7 @@ ifeq ($(TEE_SDK), TRUE)
         -config ${ENCLAVE_BASE_DIR}/src/main/resources/tee_sdk_svm.conf -key $(ENCLAVE_PRIVATE_PEM_PATH)
     endif
 endif
+
+ifeq ($(EMBEDDED_LIB_OS), TRUE)
+	/bin/bash ${BUILD_SCRIPT_DIR}/libos_occlum_enclave_build.sh
+endif
diff --git a/sdk/native/script/build_app/libos_occlum_enclave_build.sh b/sdk/native/script/build_app/libos_occlum_enclave_build.sh
new file mode 100644
index 0000000..3879514
--- /dev/null
+++ b/sdk/native/script/build_app/libos_occlum_enclave_build.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+
+enclave_target_path=${ENCLAVE_BASE_DIR}/target
+user_occlum_enclave_config_file=${ENCLAVE_BASE_DIR}/src/main/resources/embedded_libos_enclave.json
+
+# parse enclave with dependencies jar file name.
+# shellcheck disable=SC2061
+# shellcheck disable=SC2185
+# shellcheck disable=SC2035
+pushd "${enclave_target_path}"
+enclave_jar_name=$(find -name *-jar-with-dependencies.jar)
+if [[ -z $enclave_jar_name ]];
+then
+    echo "enclave with dependencies jar file is empty."
+    exit 1
+fi
+popd
+
+# create lib os enclave workspace.
+mkdir -p "${ENCLAVE_BASE_DIR}"/target/enclave_workspace/occlum_instance
+rm -rf "${ENCLAVE_BASE_DIR}"/target/enclave_workspace/occlum_instance/*
+
+pushd "${enclave_target_path}"/enclave_workspace/occlum_instance
+# create occlum instance and build occlum image.
+occlum init
+
+# update Occlum.json according to user's config file embedded_libos_enclave.json
+debuggable=$(< "${user_occlum_enclave_config_file}" jq -r '.debuggable')
+default_mmap_size=$(< "${user_occlum_enclave_config_file}" jq -r '.default_mmap_size')
+occlum_kernel_heap_size=$(< "${user_occlum_enclave_config_file}" jq -r '.kernel_space_heap_size')
+occlum_max_thread_num=$(< "${user_occlum_enclave_config_file}" jq -r '.max_num_of_threads')
+user_space_size=$(< "${user_occlum_enclave_config_file}" jq -r '.user_space_size')
+
+new_json="$(jq --arg default_mmap_size "$default_mmap_size" \
+               --arg user_space_size "$user_space_size"     \
+               --arg occlum_kernel_heap_size "$occlum_kernel_heap_size" \
+               --argjson occlum_max_thread_num "$occlum_max_thread_num" \
+               --argjson debuggable "$debuggable" \
+              '.resource_limits.user_space_size = $user_space_size |
+               .resource_limits.kernel_space_heap_size = $occlum_kernel_heap_size |
+               .resource_limits.max_num_of_threads = $occlum_max_thread_num |
+               .process.default_heap_size = "150MB" |
+               .process.default_mmap_size = $default_mmap_size |
+               .metadata.debuggable = $debuggable |
+               .entry_points = [ "/usr/lib/dragonwell11/jre/bin" ] |
+               .env.default = [ "LD_LIBRARY_PATH=/usr/lib/dragonwell11/jre/lib/server:/usr/lib/dragonwell11/jre/lib:/usr/lib/dragonwell11/jre/../lib" ]' Occlum.json)"
+
+echo "${new_json}" > Occlum.json
+
+# prepare zlib for jvm in libos occlum enclave.
+cp /opt/occlum/toolchains/gcc/x86_64-linux-musl/lib/libz.so.1.2.11 ./image/lib/libz.so.1
+
+# prepare occlum_dcap for occlum remote attestation.
+cp /opt/occlum/toolchains/dcap_lib/musl/libocclum_dcap.so.0.1.0 ./image/lib/libocclum_dcap.so.0.1.0
+
+# prepare occlum remote attestation jni.so
+mkdir -p ./image/usr/lib
+cp -r /opt/javaenclave/bin/platform/libos_occlum_enclave/libos_occlum_enclave_attestation ./image/usr/lib
+
+# prepate musl-based jvm in libos occlum enclave.
+mkdir -p ./image/usr/lib/dragonwell11/jre
+cp -r /root/tools/dragonwell-11.0.15.11+9-GA/. ./image/usr/lib/dragonwell11/jre
+
+# prepare app jar with dependencies in libos occlum enclave.
+mkdir -p ./image/usr/app
+cp -r "${enclave_target_path}"/"${enclave_jar_name}" ./image/usr/app
+
+# prepare private.pem for image signing.
+if [[ -z ${ENCLAVE_PRIVATE_PEM_PATH} ]];
+then
+    openssl genrsa -out private.pem -3 3072
+    occlum build --sign-key private.pem
+else
+    occlum build --sign-key "${ENCLAVE_PRIVATE_PEM_PATH}"
+fi
+
+if [ $debuggable ]
+then
+    # occlum package --debug > /dev/null
+    occlum package --debug > /dev/null 2>&1
+else
+    occlum package
+fi
+
+mv ./occlum_instance.tar.gz "${ENCLAVE_BASE_DIR}"/target/svm-output/lib_embedded_lib_os_enclave_load.tgz
+
+popd
\ No newline at end of file
diff --git a/sdk/native/script/build_app/make.sh b/sdk/native/script/build_app/make.sh
index cf8bfb4..1fb70f4 100644
--- a/sdk/native/script/build_app/make.sh
+++ b/sdk/native/script/build_app/make.sh
@@ -2,7 +2,6 @@
 
 # shellcheck disable=SC2006
 export BUILD_SCRIPT_DIR=`dirname "$0"`
-
 # set enclave project's base dir path.
 export ENCLAVE_BASE_DIR="$1"
 # set enclave platform, such as mock_in_svm and tee_sdk.
diff --git a/sdk/native/script/build_enclave_sdk/Makefile b/sdk/native/script/build_enclave_sdk/Makefile
index 6098d52..64088c9 100644
--- a/sdk/native/script/build_enclave_sdk/Makefile
+++ b/sdk/native/script/build_enclave_sdk/Makefile
@@ -11,9 +11,17 @@ ifeq ($(TEE_SDK), TRUE)
 	$(MAKE) -C $(ENCLAVE_BASE_DIR)/src/main/native/cpp/platform/tee_sdk_svm/remote_attestation_generate
 endif
 
+ifeq ($(EMBEDDED_LIB_OS), TRUE)
+	$(MAKE) -C $(ENCLAVE_BASE_DIR)/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate
+endif
+
 clean:
 ifeq ($(TEE_SDK), TRUE)
 	$(MAKE) -C $(ENCLAVE_BASE_DIR)/src/main/native/cpp/platform/tee_sdk_svm/wrapper clean
 	$(MAKE) -C $(ENCLAVE_BASE_DIR)/src/main/native/cpp/platform/tee_sdk_svm/edge_routines clean
 	$(MAKE) -C $(ENCLAVE_BASE_DIR)/src/main/native/cpp/platform/tee_sdk_svm/remote_attestation_generate clean
+endif
+
+ifeq ($(EMBEDDED_LIB_OS), TRUE)
+	$(MAKE) -C $(ENCLAVE_BASE_DIR)/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate clean
 endif
\ No newline at end of file
diff --git a/sdk/native/script/build_host_sdk/Makefile b/sdk/native/script/build_host_sdk/Makefile
index ceff503..95e7b5b 100644
--- a/sdk/native/script/build_host_sdk/Makefile
+++ b/sdk/native/script/build_host_sdk/Makefile
@@ -11,6 +11,16 @@ endif
 
 ifeq ($(TEE_SDK), TRUE)
 	$(MAKE) -C $(HOST_BASE_DIR)/src/main/native/cpp/platform/tee_sdk_svm
+	$(MAKE) -C $(HOST_BASE_DIR)/src/main/native/cpp/platform/libos_occlum_enclave/jni
+endif
+
+ifeq ($(EMBEDDED_LIB_OS), TRUE)
+	$(MAKE) -C $(HOST_BASE_DIR)/src/main/native/cpp/platform/libos_occlum_enclave/jni
+endif
+
+ifeq ($(TEE_SDK), TRUE)
+	$(MAKE) -C $(HOST_BASE_DIR)/src/main/native/cpp/attestation_verify/sgx/jni
+else ifeq ($(EMBEDDED_LIB_OS), TRUE)
 	$(MAKE) -C $(HOST_BASE_DIR)/src/main/native/cpp/attestation_verify/sgx/jni
 endif
 
@@ -21,5 +31,14 @@ endif
 
 ifeq ($(TEE_SDK), TRUE)
 	$(MAKE) -C $(HOST_BASE_DIR)/src/main/native/cpp/platform/tee_sdk_svm clean
+endif
+
+ifeq ($(EMBEDDED_LIB_OS), TRUE)
+	$(MAKE) -C $(HOST_BASE_DIR)/src/main/native/cpp/platform/libos_occlum_enclave/jni clean
+endif
+
+ifeq ($(TEE_SDK), TRUE)
+	$(MAKE) -C $(HOST_BASE_DIR)/src/main/native/cpp/attestation_verify/sgx/jni clean
+else ifeq ($(EMBEDDED_LIB_OS), TRUE)
 	$(MAKE) -C $(HOST_BASE_DIR)/src/main/native/cpp/attestation_verify/sgx/jni clean
 endif
\ No newline at end of file
diff --git a/sdk/native/script/build_host_sdk/make.sh b/sdk/native/script/build_host_sdk/make.sh
index 70181db..26d72cd 100644
--- a/sdk/native/script/build_host_sdk/make.sh
+++ b/sdk/native/script/build_host_sdk/make.sh
@@ -48,6 +48,13 @@ then
   # copy jni.so to target/classes, which will be packed into a jar file.
   if [[ $TEE_SDK == TRUE ]]; then
     cp -r "$NATIVE_BASE_DIR"/bin/platform/tee_sdk_svm/jni "$HOST_BASE_DIR"/target/classes
+  fi
+  # copy jni.so to target/classes, which will be packed into a jar file.
+  if [[ $EMBEDDED_LIB_OS == TRUE ]]; then
+    cp -r "$NATIVE_BASE_DIR"/bin/platform/libos_occlum_enclave/jni "$HOST_BASE_DIR"/target/classes
+  fi
+  # copy sgx remote attestation verification jni.so to target/classes, which will be packed into a jar file.
+  if [ "$TEE_SDK" == TRUE ] || [ "$EMBEDDED_LIB_OS" == TRUE ]; then
     cp -r "$NATIVE_BASE_DIR"/bin/remote_attestation "$HOST_BASE_DIR"/target/classes
   fi
 else
diff --git a/sdk/pom.xml b/sdk/pom.xml
index 653eadc..bfe67d9 100644
--- a/sdk/pom.xml
+++ b/sdk/pom.xml
@@ -11,10 +11,20 @@
         <maven.compiler.source>11</maven.compiler.source>
         <maven.compiler.target>11</maven.compiler.target>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <com.alibaba.enclave.platform>MOCK_IN_SVM:TEE_SDK</com.alibaba.enclave.platform>
+        <com.alibaba.enclave.platform>MOCK_IN_SVM:TEE_SDK:EMBEDDED_LIB_OS</com.alibaba.enclave.platform>
     </properties>
     <dependencyManagement>
         <dependencies>
+            <dependency>
+                <groupId>org.apache.commons</groupId>
+                <artifactId>commons-compress</artifactId>
+                <version>1.19</version>
+            </dependency>
+            <dependency>
+                <groupId>org.json</groupId>
+                <artifactId>json</artifactId>
+                <version>20211205</version>
+            </dependency>
             <dependency>
                 <groupId>com.alibaba.confidentialcomputing</groupId>
                 <artifactId>common</artifactId>
diff --git a/test/enclave/pom.xml b/test/enclave/pom.xml
index 2bbb426..64e3d9f 100644
--- a/test/enclave/pom.xml
+++ b/test/enclave/pom.xml
@@ -123,6 +123,25 @@
                     </execution>
                 </executions>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <version>3.3.0</version>
+                <configuration>
+                    <descriptorRefs>
+                        <descriptorRef>jar-with-dependencies</descriptorRef>
+                    </descriptorRefs>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>make-assembly</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
@@ -179,4 +198,4 @@
             <scope>test</scope>
         </dependency>
     </dependencies>
-</project>
+</project>
\ No newline at end of file
diff --git a/test/enclave/src/main/resources/embedded_libos_enclave.json b/test/enclave/src/main/resources/embedded_libos_enclave.json
new file mode 100644
index 0000000..655b56a
--- /dev/null
+++ b/test/enclave/src/main/resources/embedded_libos_enclave.json
@@ -0,0 +1,11 @@
+{
+  "debuggable": false,
+  "agent_http_handler_thread_pool_size": 6,
+  "enclave_startup_duration_ms": 60000,
+  "kernel_space_heap_size": "32MB",
+  "user_space_size": "1200MB",
+  "default_mmap_size": "800MB",
+  "max_num_of_threads": 48,
+  "log_level": "off",
+  "enclave_jvm_args": ["-XX:-UseCompressedOops", "-Xmx512m", "-Dos.name=Linux"]
+}
\ No newline at end of file
diff --git a/test/host/pom.xml b/test/host/pom.xml
index ceacc29..9073a33 100644
--- a/test/host/pom.xml
+++ b/test/host/pom.xml
@@ -19,6 +19,7 @@
                 <includes>
                     <include>**/*.so</include>
                     <include>**/*.signed</include>
+                    <include>**/*.tgz</include>
                 </includes>
             </resource>
         </resources>
@@ -42,6 +43,9 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
+                <!--configuration>
+                     <forkCount>0</forkCount>
+                </configuration-->
                 <version>3.0.0-M5</version>
             </plugin>
         </plugins>
diff --git a/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestJavaEnclaveService.java b/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestJavaEnclaveService.java
index 741bb3d..d589c65 100644
--- a/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestJavaEnclaveService.java
+++ b/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestJavaEnclaveService.java
@@ -2,6 +2,7 @@ package com.alibaba.confidentialcomputing.test.host;
 
 import java.io.IOException;
 import java.util.Iterator;
+import java.util.Random;
 
 import com.alibaba.confidentialcomputing.host.*;
 import com.alibaba.confidentialcomputing.host.exception.EnclaveCreatingException;
@@ -21,13 +22,28 @@ public class TestJavaEnclaveService {
     private String sayHelloService(EnclaveType type, String plain) throws
             EnclaveCreatingException, ServicesLoadingException, EnclaveDestroyingException, RemoteAttestationException, IOException {
         Enclave enclave = EnclaveFactory.create(type);
+        assertNotNull(enclave);
+        byte[] userData = new byte[64];
+        new Random().nextBytes(userData);
         if (type == EnclaveType.TEE_SDK) {
-            TeeSdkAttestationReport report = (TeeSdkAttestationReport) RemoteAttestation.generateAttestationReport(enclave, null);
+            TeeSdkAttestationReport report = (TeeSdkAttestationReport) RemoteAttestation.generateAttestationReport(enclave, userData);
             assertEquals(report.getEnclaveType(), EnclaveType.TEE_SDK);
             assertNotNull(report.getQuote());
             assertEquals(0, RemoteAttestation.verifyAttestationReport(report));
             assertNotNull(report.getMeasurementEnclave());
             assertNotNull(report.getMeasurementSigner());
+            assertNotNull(report.getUserData());
+            assertArrayEquals(userData, report.getUserData());
+        }
+        if (type == EnclaveType.EMBEDDED_LIB_OS) {
+            EmbeddedLibOSAttestationReport report = (EmbeddedLibOSAttestationReport) RemoteAttestation.generateAttestationReport(enclave, userData);
+            assertEquals(report.getEnclaveType(), EnclaveType.EMBEDDED_LIB_OS);
+            assertNotNull(report.getQuote());
+            assertEquals(0, RemoteAttestation.verifyAttestationReport(report));
+            assertNotNull(report.getMeasurementEnclave());
+            assertNotNull(report.getMeasurementSigner());
+            assertNotNull(report.getUserData());
+            assertArrayEquals(userData, report.getUserData());
         }
         Iterator<SayHelloService> userServices = enclave.load(SayHelloService.class);
         assertNotNull(userServices);
@@ -41,13 +57,28 @@ public class TestJavaEnclaveService {
 
     private void reflectionCallService(EnclaveType type) throws EnclaveCreatingException, ServicesLoadingException, EnclaveDestroyingException, RemoteAttestationException {
         Enclave enclave = EnclaveFactory.create(type);
+        assertNotNull(enclave);
+        byte[] userData = new byte[64];
+        new Random().nextBytes(userData);
         if (type == EnclaveType.TEE_SDK) {
-            TeeSdkAttestationReport report = (TeeSdkAttestationReport) RemoteAttestation.generateAttestationReport(enclave, null);
+            TeeSdkAttestationReport report = (TeeSdkAttestationReport) RemoteAttestation.generateAttestationReport(enclave, userData);
             assertEquals(report.getEnclaveType(), EnclaveType.TEE_SDK);
             assertNotNull(report.getQuote());
             assertEquals(0, RemoteAttestation.verifyAttestationReport(report));
             assertNotNull(report.getMeasurementEnclave());
             assertNotNull(report.getMeasurementSigner());
+            assertNotNull(report.getUserData());
+            assertArrayEquals(userData, report.getUserData());
+        }
+        if (type == EnclaveType.EMBEDDED_LIB_OS) {
+            EmbeddedLibOSAttestationReport report = (EmbeddedLibOSAttestationReport) RemoteAttestation.generateAttestationReport(enclave, userData);
+            assertEquals(report.getEnclaveType(), EnclaveType.EMBEDDED_LIB_OS);
+            assertNotNull(report.getQuote());
+            assertEquals(0, RemoteAttestation.verifyAttestationReport(report));
+            assertNotNull(report.getMeasurementEnclave());
+            assertNotNull(report.getMeasurementSigner());
+            assertNotNull(report.getUserData());
+            assertArrayEquals(userData, report.getUserData());
         }
         Iterator<ReflectionCallService> userServices = enclave.load(ReflectionCallService.class);
         assertNotNull(userServices);
@@ -60,13 +91,28 @@ public class TestJavaEnclaveService {
 
     private void javaEnclaveException(EnclaveType type) throws EnclaveCreatingException, ServicesLoadingException, EnclaveDestroyingException, RemoteAttestationException {
         Enclave enclave = EnclaveFactory.create(type);
+        assertNotNull(enclave);
+        byte[] userData = new byte[64];
+        new Random().nextBytes(userData);
         if (type == EnclaveType.TEE_SDK) {
-            TeeSdkAttestationReport report = (TeeSdkAttestationReport) RemoteAttestation.generateAttestationReport(enclave, null);
+            TeeSdkAttestationReport report = (TeeSdkAttestationReport) RemoteAttestation.generateAttestationReport(enclave, userData);
             assertEquals(report.getEnclaveType(), EnclaveType.TEE_SDK);
             assertNotNull(report.getQuote());
             assertEquals(0, RemoteAttestation.verifyAttestationReport(report));
             assertNotNull(report.getMeasurementEnclave());
             assertNotNull(report.getMeasurementSigner());
+            assertNotNull(report.getUserData());
+            assertArrayEquals(userData, report.getUserData());
+        }
+        if (type == EnclaveType.EMBEDDED_LIB_OS) {
+            EmbeddedLibOSAttestationReport report = (EmbeddedLibOSAttestationReport) RemoteAttestation.generateAttestationReport(enclave, userData);
+            assertEquals(report.getEnclaveType(), EnclaveType.EMBEDDED_LIB_OS);
+            assertNotNull(report.getQuote());
+            assertEquals(0, RemoteAttestation.verifyAttestationReport(report));
+            assertNotNull(report.getMeasurementEnclave());
+            assertNotNull(report.getMeasurementSigner());
+            assertNotNull(report.getUserData());
+            assertArrayEquals(userData, report.getUserData());
         }
         Iterator<EnclaveException> userServices = enclave.load(EnclaveException.class);
         assertNotNull(userServices);
@@ -77,24 +123,38 @@ public class TestJavaEnclaveService {
     }
 
     @Test
-    public void testSayHelloService() throws
-            EnclaveCreatingException, EnclaveDestroyingException, ServicesLoadingException, RemoteAttestationException, IOException {
-        assertEquals("Hello World", sayHelloService(EnclaveType.MOCK_IN_JVM, "Hello World"));
-        assertEquals("Hello World", sayHelloService(EnclaveType.MOCK_IN_SVM, "Hello World"));
-        assertEquals("Hello World", sayHelloService(EnclaveType.TEE_SDK, "Hello World"));
+    public void testSayHelloService() {
+        try {
+            assertEquals("Hello World", sayHelloService(EnclaveType.MOCK_IN_JVM, "Hello World"));
+            assertEquals("Hello World", sayHelloService(EnclaveType.MOCK_IN_SVM, "Hello World"));
+            assertEquals("Hello World", sayHelloService(EnclaveType.TEE_SDK, "Hello World"));
+            assertEquals("Hello World", sayHelloService(EnclaveType.EMBEDDED_LIB_OS, "Hello World"));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
     }
 
     @Test
-    public void testReflectionCallService() throws ServicesLoadingException, EnclaveCreatingException, EnclaveDestroyingException, RemoteAttestationException {
-        reflectionCallService(EnclaveType.MOCK_IN_JVM);
-        reflectionCallService(EnclaveType.MOCK_IN_SVM);
-        reflectionCallService(EnclaveType.TEE_SDK);
+    public void testReflectionCallService() {
+        try {
+            reflectionCallService(EnclaveType.MOCK_IN_JVM);
+            reflectionCallService(EnclaveType.MOCK_IN_SVM);
+            reflectionCallService(EnclaveType.TEE_SDK);
+            reflectionCallService(EnclaveType.EMBEDDED_LIB_OS);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
     }
 
     @Test
-    public void testJavaEnclaveException() throws ServicesLoadingException, EnclaveCreatingException, EnclaveDestroyingException, RemoteAttestationException {
-        javaEnclaveException(EnclaveType.MOCK_IN_JVM);
-        javaEnclaveException(EnclaveType.MOCK_IN_SVM);
-        javaEnclaveException(EnclaveType.TEE_SDK);
+    public void testJavaEnclaveException() {
+        try {
+            javaEnclaveException(EnclaveType.MOCK_IN_JVM);
+            javaEnclaveException(EnclaveType.MOCK_IN_SVM);
+            javaEnclaveException(EnclaveType.TEE_SDK);
+            javaEnclaveException(EnclaveType.EMBEDDED_LIB_OS);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
     }
 }
diff --git a/test/pom.xml b/test/pom.xml
index 7c2f566..97e1d9b 100644
--- a/test/pom.xml
+++ b/test/pom.xml
@@ -12,7 +12,7 @@
         <maven.compiler.source>11</maven.compiler.source>
         <maven.compiler.target>11</maven.compiler.target>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <com.alibaba.enclave.platform>MOCK_IN_SVM:TEE_SDK</com.alibaba.enclave.platform>
+        <com.alibaba.enclave.platform>MOCK_IN_SVM:TEE_SDK:EMBEDDED_LIB_OS</com.alibaba.enclave.platform>
     </properties>
     <dependencyManagement>
         <dependencies>
diff --git a/tools/cicd/Dockerfile b/tools/cicd/Dockerfile
index a611185..544392d 100644
--- a/tools/cicd/Dockerfile
+++ b/tools/cicd/Dockerfile
@@ -6,23 +6,29 @@ ENV APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1
 ENV DEBIAN_FRONTEND noninteractive
 
 ADD ["graalvm-enclave-22.1.0.tar", "/root/tools/"]
-ADD ["x86_64-linux-musl-native.tgz", "/root/tools/"]
 ADD ["zlib-1.2.11.tar.gz", "/root/tools/"]
 ADD ["settings.xml", "/root/tools/"]
+ADD ["zlib-1.2.11.tar.gz", "/root/tools/"]
+ADD ["Alibaba_Dragonwell_11.0.15.11.9_x64_alpine-linux.tar.gz", "/root/tools"]
 ADD ["sgx_linux_x64_sdk_2.17.100.0.bin", "/root/tools/"]
 ENV GRAALVM_HOME "/root/tools/graalvm-enclave-22.1.0"
 ENV JAVA_HOME "/root/tools/graalvm-enclave-22.1.0"
-ENV CC "/root/tools/x86_64-linux-musl-native/bin/gcc"
-ENV PATH $PATH:"/root/tools/x86_64-linux-musl-native/bin"
+ENV PATH="/opt/occlum/build/bin:/usr/local/occlum/bin:$PATH"
+ENV CC=/usr/local/occlum/bin/occlum-gcc
 
 ARG PSW_VERSION=2.17.100.3
 ARG DCAP_VERSION=1.14.100.3
 
 # install necessary tools.
-RUN apt-get update && apt-get install -y gdb gnupg wget aptitude && \
+RUN apt-get update && apt-get install -y gdb gnupg wget aptitude libfuse-dev libtool tzdata jq && \
+    echo -e 'yes\n' | apt-get install -y maven && \
+    echo -e 'yes\n' | apt-get install -y build-essential libz-dev zlib1g-dev && \
     echo 'deb [arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu bionic main' > /etc/apt/sources.list.d/intel-sgx.list && \
     wget -qO - https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key | apt-key add - && \
+    echo 'deb [arch=amd64] https://occlum.io/occlum-package-repos/debian bionic main' | tee /etc/apt/sources.list.d/occlum.list && \
+    wget -qO - https://occlum.io/occlum-package-repos/debian/public.key | apt-key add - && \
     apt-get update && aptitude install -y \
+    occlum \
     libsgx-launch-dev=$PSW_VERSION-bionic1 \
     libsgx-urts=$PSW_VERSION-bionic1 \
     libsgx-urts-dbgsym=$PSW_VERSION-bionic1 \
@@ -32,5 +38,8 @@ RUN apt-get update && apt-get install -y gdb gnupg wget aptitude && \
     libsgx-dcap-default-qpl=$DCAP_VERSION-bionic1 && \
     echo -e 'yes\n' | apt-get install -y maven && \
     echo -e 'yes\n' | apt-get install -y build-essential libz-dev zlib1g-dev && \
-    cd /root/tools/zlib-1.2.11 && ./configure --prefix=/root/tools/x86_64-linux-musl-native --static && make && make install && \
+    cd /root/tools/zlib-1.2.11 && ./configure --prefix=/opt/occlum/toolchains/gcc/x86_64-linux-musl && make && make install && \
     cd /root/tools && chmod 777 sgx_linux_x64_sdk_2.17.100.0.bin && echo -e 'no\n/opt/teesdk\n' | ./sgx_linux_x64_sdk_2.17.100.0.bin
+
+# copy dcap_occlum lib from occlum docker image.
+COPY --from=occlum/occlum:0.26.4-ubuntu18.04 /opt/occlum/toolchains/dcap_lib /opt/occlum/toolchains/dcap_lib
\ No newline at end of file
diff --git a/tools/cicd/make.sh b/tools/cicd/make.sh
index f4667ea..5dc43d0 100755
--- a/tools/cicd/make.sh
+++ b/tools/cicd/make.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 
 BUILD_IMAGE=javaenclave_build
-BUILD_TAG=v0.1.9
+BUILD_TAG=v0.1.10
 
 SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
 
@@ -14,15 +14,15 @@ if [[ "$(docker images -q ${BUILD_IMAGE}:${BUILD_TAG} 2> /dev/null)" == "" ]]; t
   # Get the customized Graal VM from git@gitlab.alibaba-inc.com:graal/SGXGraalVM.git
   # This should be replaced to the offical version when all patches are accepted by the Graal community
   wget https://graal.oss-cn-beijing.aliyuncs.com/graal-enclave/JDK11-22.1.0/graalvm-enclave-22.1.0.tar
-  wget http://graal.oss-cn-beijing.aliyuncs.com/graal-enclave/x86_64-linux-musl-native.tgz
   wget http://graal.oss-cn-beijing.aliyuncs.com/graal-enclave/zlib-1.2.11.tar.gz
   wget http://graal.oss-cn-beijing.aliyuncs.com/graal-enclave/settings_taobao.xml -O settings.xml
   wget https://dragonwell.oss-cn-shanghai.aliyuncs.com/11/tee_java/dependency/sgx_linux_x64_sdk_2.17.100.0.bin
+  wget https://dragonwell.oss-cn-shanghai.aliyuncs.com/11.0.15.11.9/Alibaba_Dragonwell_11.0.15.11.9_x64_alpine-linux.tar.gz
   docker build -t ${BUILD_IMAGE}:${BUILD_TAG} .
   rm -f graalvm-enclave-22.1.0.tar
-  rm -f x86_64-linux-musl-native.tgz
   rm -f zlib-1.2.11.tar.gz
   rm -f sgx_linux_x64_sdk_2.17.100.0.bin
+  rm -f Alibaba_Dragonwell_11.0.15.11.9_x64_alpine-linux.tar.gz
 fi
 
 # Set PCCS for DCAP Remote Attestation.


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org