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 7afe3a6d10eee8fb28149d9f34c26c0dba0e3d72
Author: jeffery.wsj <[email protected]>
AuthorDate: Thu Jan 6 10:56:07 2022 +0800

    [sdk] Implement JavaEnclave SDK fractional features of host-side
    
    Summary:
    1. Define invocation interfaces between host-side and enclave-side.
    2. Implement service load and invoking operation of the host-side.
    3. Define and implement exceptions handling mechanism from the enclave-side.
    4. Add a mock enclave for the unit test.
    
    Reviewers: lei.yul, cengfeng.lzy, sanhong.lsh
    
    Issue: https://aone.alibaba-inc.com/task/38948515
    
    CR: 
https://code.aone.alibaba-inc.com/java-tee/JavaEnclave/codereview/7455358
---
 sdk/{enclave => common}/pom.xml                    |   6 +-
 .../common/EnclaveInvocationContext.java           |  70 ++++++
 .../common/EnclaveInvocationResult.java            |  41 ++++
 .../common/SerializationHelper.java                |  38 ++++
 .../common/ServiceHandler.java                     |  57 +++++
 sdk/enclave/pom.xml                                |   6 +-
 .../exception/ConfidentialComputingException.java  |   8 +
 sdk/host/pom.xml                                   |  79 ++++++-
 .../host/AbstractEnclave.java                      | 235 +++++++++++++++++++++
 .../host/BaseEnclaveServicesRecycler.java          |  18 ++
 .../confidentialcomputing/host/Enclave.java        |   4 +-
 .../host/EnclaveConfigure.java                     |  85 ++++++++
 .../confidentialcomputing/host/EnclaveDebug.java   |  29 +++
 .../confidentialcomputing/host/EnclaveFactory.java |   4 +-
 .../host/EnclaveServicesRecycler.java              |  62 ++++++
 .../confidentialcomputing/host/EnclaveToken.java   |  46 ++++
 .../confidentialcomputing/host/ExtractLibrary.java |  34 +++
 .../host/InnerNativeInvocationResult.java          |  27 +++
 .../host/MockInJvmEnclave.java                     |  32 +++
 .../host/MockInSvmEnclave.java                     | 214 +++++++++++++++++++
 .../host/ProxyEnclaveInvocationHandler.java        |  87 ++++++++
 .../confidentialcomputing/host/TeeSdkEnclave.java  | 164 ++++++++++++++
 .../exception/ConfidentialComputingException.java  |  52 +++++
 .../host/exception/EnclaveCreatingException.java   |  12 +-
 .../host/exception/EnclaveDestroyingException.java |  12 +-
 .../exception/EnclaveMethodInvokingException.java  |  30 +++
 .../host/exception/ServicesLoadingException.java   |  12 +-
 .../host/exception/ServicesUnloadingException.java |  30 +++
 .../host/MockTestEnclave.java                      | 166 +++++++++++++++
 .../confidentialcomputing/host/Service.java        |  11 +
 .../host/ServiceExceptionTest.java                 |   7 +
 .../confidentialcomputing/host/ServiceImpl.java    |  26 +++
 .../host/TestAbstractEnclave.java                  |  46 ++++
 .../host/TestEnclaveFactory.java                   |  16 ++
 sdk/pom.xml                                        |  28 ++-
 35 files changed, 1776 insertions(+), 18 deletions(-)

diff --git a/sdk/enclave/pom.xml b/sdk/common/pom.xml
similarity index 95%
copy from sdk/enclave/pom.xml
copy to sdk/common/pom.xml
index 7a81e07..1601dfb 100644
--- a/sdk/enclave/pom.xml
+++ b/sdk/common/pom.xml
@@ -8,9 +8,9 @@
         <artifactId>JavaEnclave</artifactId>
         <version>0.1.0</version>
     </parent>
-    <artifactId>enclave</artifactId>
+    <artifactId>common</artifactId>
     <packaging>jar</packaging>
-    <name>JavaEnclave-Enclave</name>
+    <name>JavaEnclave-Common</name>
     <url></url>
     <build>
         <plugins>
@@ -20,7 +20,7 @@
                 <version>0.8.3</version>
                 <configuration>
                     <includes>
-                        
<include>com/alibaba/confidentialcomputing/**/*</include>
+                        
<include>com/alibaba/confidentialcomputing/common/*</include>
                     </includes>
                 </configuration>
                 <executions>
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
new file mode 100644
index 0000000..9a1f3be
--- /dev/null
+++ 
b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EnclaveInvocationContext.java
@@ -0,0 +1,70 @@
+package com.alibaba.confidentialcomputing.common;
+
+import java.io.Serializable;
+
+/**
+ * EnclaveInvocationInputMeta stores a method's necessary information for 
reflection
+ * call, include object's unique instanceIdentity、interface name、class 
name、method
+ * signature name, and its parameters.
+ */
+public final class EnclaveInvocationContext implements Serializable {
+    private static final long serialVersionUID = 6878585714134748604L;
+
+    private final ServiceHandler serviceHandler;
+    private final String methodName;
+    private final String[] parameterTypes;
+    private final Object[] arguments;
+
+    public EnclaveInvocationContext(ServiceHandler serviceHandler,
+                                    String methodName,
+                                    String[] parameterTypes,
+                                    Object[] arguments) {
+        this.serviceHandler = serviceHandler;
+        this.methodName = methodName;
+        this.parameterTypes = parameterTypes;
+        this.arguments = arguments;
+    }
+
+    public EnclaveInvocationContext(ServiceHandler serviceHandler) {
+        this.methodName = null;
+        this.parameterTypes = null;
+        this.arguments = null;
+        this.serviceHandler = serviceHandler;
+    }
+
+    /**
+     * get service handler.
+     *
+     * @return service handler.
+     */
+    public ServiceHandler getServiceHandler() {
+        return serviceHandler;
+    }
+
+    /**
+     * get the method's name.
+     *
+     * @return method's name.
+     */
+    public String getMethodName() {
+        return methodName;
+    }
+
+    /**
+     * get all parameters' type.
+     *
+     * @return parameters' type information.
+     */
+    public String[] getParameterTypes() {
+        return parameterTypes;
+    }
+
+    /**
+     * get all arguments' value.
+     *
+     * @return arguments' value information.
+     */
+    public Object[] getArguments() {
+        return arguments;
+    }
+}
diff --git 
a/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EnclaveInvocationResult.java
 
b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EnclaveInvocationResult.java
new file mode 100644
index 0000000..b664304
--- /dev/null
+++ 
b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EnclaveInvocationResult.java
@@ -0,0 +1,41 @@
+package com.alibaba.confidentialcomputing.common;
+
+import java.io.Serializable;
+
+/**
+ * EnclaveInvocationResult is a service's method invoking return value in an 
enclave.
+ * If an exception happened during the invocation, the exception will be 
stored in the
+ * EnclaveInvocationResult object's exception field, the result field will be 
null.
+ * If no exception happened during the invocation, the method invoking return 
value is
+ * stored in the EnclaveInvocationResult object's result field, and the 
exception field
+ * will be null.
+ */
+public final class EnclaveInvocationResult implements Serializable {
+    private static final long serialVersionUID = -571664787738930979L;
+
+    private final Object resultedValue;
+    private final Throwable exception;
+
+    public EnclaveInvocationResult(Object result, Throwable exception) {
+        this.resultedValue = result;
+        this.exception = exception;
+    }
+
+    /**
+     * get method's return value.
+     *
+     * @return method's return value.
+     */
+    public Object getResult() {
+        return this.resultedValue;
+    }
+
+    /**
+     * get exception during method's invocation.
+     *
+     * @return exception during method's invocation if it has.
+     */
+    public Throwable getException() {
+        return this.exception;
+    }
+}
\ No newline at end of file
diff --git 
a/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/SerializationHelper.java
 
b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/SerializationHelper.java
new file mode 100644
index 0000000..5b678ab
--- /dev/null
+++ 
b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/SerializationHelper.java
@@ -0,0 +1,38 @@
+package com.alibaba.confidentialcomputing.common;
+
+import java.io.IOException;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+/**
+ * SerializationHelper is a helper class to process Object's serialization and 
deserialization.
+ */
+public final class SerializationHelper {
+    /**
+     * serialization helper method.
+     *
+     * @return serialization result.
+     * @throws IOException {@link IOException} If serialization failed.
+     */
+    public static byte[] serialize(Object data) throws IOException {
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        ObjectOutputStream oos = new ObjectOutputStream(bos);
+        oos.writeObject(data);
+        return bos.toByteArray();
+    }
+
+    /**
+     * deserialization helper method.
+     *
+     * @return deserialization result.
+     * @throws IOException            {@link IOException} If deserialization 
failed.
+     * @throws ClassNotFoundException {@link ClassNotFoundException} If 
deserialization failed.
+     */
+    public static Object deserialize(byte[] data) throws IOException, 
ClassNotFoundException {
+        ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
+        ObjectInputStream ois = new ObjectInputStream(inputStream);
+        return ois.readObject();
+    }
+}
\ No newline at end of file
diff --git 
a/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/ServiceHandler.java
 
b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/ServiceHandler.java
new file mode 100644
index 0000000..b81632e
--- /dev/null
+++ 
b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/ServiceHandler.java
@@ -0,0 +1,57 @@
+package com.alibaba.confidentialcomputing.common;
+
+import java.io.Serializable;
+
+/**
+ * ServiceHandler is a handler object in host to the real service loaded in 
the enclave.
+ * A ServiceHandler object will be bound to a host proxy handler.
+ */
+public final class ServiceHandler implements Serializable {
+    private static final long serialVersionUID = -879933256236932801L;
+
+    // instanceIdentity indicates the global unique service object's index in 
one enclave.
+    private final String instanceIdentity;
+    // serviceImplClass stores loaded service object's full signature in the 
enclave.
+    private final String serviceImplClass;
+    // serviceInterface stores loaded service object's implement interface's 
full signature in the enclave.
+    private final String serviceInterface;
+
+    public ServiceHandler(String serviceInterfaceName, String 
serviceClassName, String instanceIdentity) {
+        this.serviceInterface = serviceInterfaceName;
+        this.serviceImplClass = serviceClassName;
+        this.instanceIdentity = instanceIdentity;
+    }
+
+    public ServiceHandler(String interfaceName) {
+        this.instanceIdentity = null;
+        this.serviceImplClass = null;
+        this.serviceInterface = interfaceName;
+    }
+
+    /**
+     * get service's unique identity.
+     *
+     * @return service's unique identity.
+     */
+    public String getInstanceIdentity() {
+        return this.instanceIdentity;
+    }
+
+    /**
+     * get service's interface name.
+     *
+     * @return service's interface name.
+     */
+    public String getServiceInterfaceName() {
+        return this.serviceInterface;
+    }
+
+    /**
+     * get service's class name.
+     *
+     * @return service's class name.
+     */
+    public String getServiceImplClassName() {
+        return this.serviceImplClass;
+    }
+}
\ No newline at end of file
diff --git a/sdk/enclave/pom.xml b/sdk/enclave/pom.xml
index 7a81e07..9b47431 100644
--- a/sdk/enclave/pom.xml
+++ b/sdk/enclave/pom.xml
@@ -20,7 +20,7 @@
                 <version>0.8.3</version>
                 <configuration>
                     <includes>
-                        
<include>com/alibaba/confidentialcomputing/**/*</include>
+                        
<include>com/alibaba/confidentialcomputing/enclave/**/*</include>
                     </includes>
                 </configuration>
                 <executions>
@@ -57,5 +57,9 @@
             <artifactId>junit-jupiter-engine</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>com.alibaba.confidentialcomputing</groupId>
+            <artifactId>common</artifactId>
+        </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git 
a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/exception/ConfidentialComputingException.java
 
b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/exception/ConfidentialComputingException.java
index 51b4c93..f525dcf 100644
--- 
a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/exception/ConfidentialComputingException.java
+++ 
b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/exception/ConfidentialComputingException.java
@@ -20,4 +20,12 @@ public class ConfidentialComputingException extends 
Exception {
     public ConfidentialComputingException(Throwable e) {
         super(e);
     }
+
+    /**
+     * @param info exception information.
+     * @param e    exception.
+     */
+    public ConfidentialComputingException(String info, Throwable e) {
+        super(info, e);
+    }
 }
\ No newline at end of file
diff --git a/sdk/host/pom.xml b/sdk/host/pom.xml
index d017234..d2f5fc2 100644
--- a/sdk/host/pom.xml
+++ b/sdk/host/pom.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
     <modelVersion>4.0.0</modelVersion>
     <groupId>com.alibaba.confidentialcomputing</groupId>
     <parent>
@@ -13,8 +14,82 @@
     <url></url>
     <build>
         <plugins>
+            <plugin>
+                <groupId>org.jacoco</groupId>
+                <artifactId>jacoco-maven-plugin</artifactId>
+                <version>0.8.3</version>
+                <configuration>
+                    <includes>
+                        
<include>com/alibaba/confidentialcomputing/host/*</include>
+                        
<include>com/alibaba/confidentialcomputing/host/**/*</include>
+                    </includes>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>pre-test</id>
+                        <goals>
+                            <goal>prepare-agent</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>post-test</id>
+                        <phase>test</phase>
+                        <goals>
+                            <goal>report</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>3.0.0-M5</version>
+            </plugin>
         </plugins>
     </build>
     <dependencies>
+        <dependency>
+            <groupId>com.alibaba.confidentialcomputing</groupId>
+            <artifactId>common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.auto.service</groupId>
+            <artifactId>auto-service-annotations</artifactId>
+            <version>1.0-rc6</version>
+            <optional>true</optional>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.auto.service</groupId>
+            <artifactId>auto-service</artifactId>
+            <version>1.0-rc6</version>
+            <optional>true</optional>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jacoco</groupId>
+            <artifactId>jacoco-maven-plugin</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.platform</groupId>
+            <artifactId>junit-platform-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit-pioneer</groupId>
+            <artifactId>junit-pioneer</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
-</project>
\ No newline at end of file
+</project>
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
new file mode 100644
index 0000000..37c87a9
--- /dev/null
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/AbstractEnclave.java
@@ -0,0 +1,235 @@
+package com.alibaba.confidentialcomputing.host;
+
+import java.io.IOException;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ServiceLoader;
+
+import com.alibaba.confidentialcomputing.common.EnclaveInvocationResult;
+import com.alibaba.confidentialcomputing.common.EnclaveInvocationContext;
+import com.alibaba.confidentialcomputing.common.SerializationHelper;
+import com.alibaba.confidentialcomputing.common.ServiceHandler;
+import 
com.alibaba.confidentialcomputing.host.exception.EnclaveCreatingException;
+import 
com.alibaba.confidentialcomputing.host.exception.EnclaveMethodInvokingException;
+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.
+ * But the underlying native implements is very different between these 
enclave platforms,
+ * so enclave will implement these native calls in specific enclave platform.
+ */
+abstract class AbstractEnclave implements Enclave {
+    private final EnclaveContext enclaveContext;
+
+    AbstractEnclave(EnclaveType type,
+                    EnclaveDebug mode,
+                    BaseEnclaveServicesRecycler recycler) throws 
EnclaveCreatingException {
+        if (type == EnclaveType.TEE_SDK && mode == EnclaveDebug.NONE) {
+            throw new EnclaveCreatingException("TEE SDK enclave's debug mode 
must be RELEASE or DEBUG.");
+        }
+        enclaveContext = new EnclaveContext(type, mode, recycler);
+    }
+
+    AbstractEnclave(EnclaveType type, BaseEnclaveServicesRecycler recycler) {
+        enclaveContext = new EnclaveContext(type, EnclaveDebug.NONE, recycler);
+    }
+
+    EnclaveContext getEnclaveContext() {
+        return enclaveContext;
+    }
+
+    abstract InnerNativeInvocationResult loadServiceNative(byte[] payload);
+
+    abstract InnerNativeInvocationResult unloadServiceNative(byte[] payload);
+
+    abstract InnerNativeInvocationResult invokeMethodNative(byte[] payload);
+
+    // load service by interface name.
+    ServiceHandler[] loadService(Class<?> service) throws 
ServicesLoadingException {
+        if (!getEnclaveContext().getEnclaveToken().tryAcquireToken()) {
+            throw new ServicesLoadingException("enclave was destroyed.");
+        }
+        try {
+            // Only need to provide service's interface name is enough to load 
service
+            // in enclave.
+            EnclaveInvocationContext parasWrapper = new 
EnclaveInvocationContext(
+                    new ServiceHandler(service.getName()));
+            byte[] payload;
+            try {
+                payload = SerializationHelper.serialize(parasWrapper);
+            } catch (IOException e) {
+                throw new ServicesLoadingException("EnclaveInvokeMetaWrapper 
serialization failed.", e);
+            }
+            InnerNativeInvocationResult resultNativeWrapper = 
loadServiceNative(payload);
+            // If loadServiceNative native call return value is error, an 
ServicesLoadingException exception
+            // will be thrown.
+            if (resultNativeWrapper.getRet() != 0) {
+                throw new ServicesLoadingException("load service native call 
failed.");
+            }
+            EnclaveInvocationResult resultWrapper;
+            try {
+                resultWrapper = (EnclaveInvocationResult) 
SerializationHelper.deserialize(resultNativeWrapper.getPayload());
+            } catch (IOException | ClassNotFoundException e) {
+                throw new ServicesLoadingException("EnclaveInvokeResultWrapper 
deserialization failed.", e);
+            }
+            Throwable exception = resultWrapper.getException();
+            Object result = resultWrapper.getResult();
+            // this exception is transformed from enclave, so throw it and 
handle it in proxy handler.
+            if (exception != null) {
+                throw new ServicesLoadingException("service load exception 
happened in enclave.", exception);
+            }
+            // result should never be null, at least it should have an empty 
ServiceMirror type array.
+            if (result == null) {
+                throw new ServicesLoadingException("service load with no any 
result.");
+            }
+            if (!(result instanceof ServiceHandler[])) {
+                throw new ServicesLoadingException("service load return type 
is not ServiceHandler[].");
+            }
+            return (ServiceHandler[]) result;
+        } finally {
+            getEnclaveContext().getEnclaveToken().restoreToken();
+        }
+    }
+
+    // unload service by interface name、class name and service's unique 
identity in enclave.
+    // it was called if the service handler was recycled by gc in host side.
+    void unloadService(ServiceHandler service) throws 
ServicesUnloadingException {
+        if (!getEnclaveContext().getEnclaveToken().tryAcquireToken()) {
+            throw new ServicesUnloadingException("enclave was destroyed.");
+        }
+        try {
+            EnclaveInvocationContext parasWrapper = new 
EnclaveInvocationContext(service);
+            byte[] payload;
+            try {
+                payload = SerializationHelper.serialize(parasWrapper);
+            } catch (IOException e) {
+                throw new ServicesUnloadingException("EnclaveInvokeMetaWrapper 
serialization failed.", e);
+            }
+            InnerNativeInvocationResult resultNativeWrapper = 
unloadServiceNative(payload);
+            if (resultNativeWrapper.getRet() != 0) {
+                throw new ServicesUnloadingException("unload service native 
call failed.");
+            }
+            EnclaveInvocationResult resultWrapper;
+            try {
+                resultWrapper = (EnclaveInvocationResult) 
SerializationHelper.deserialize(resultNativeWrapper.getPayload());
+            } catch (IOException | ClassNotFoundException e) {
+                throw new 
ServicesUnloadingException("EnclaveInvokeResultWrapper deserialization 
failed.", e);
+            }
+            Throwable exception = resultWrapper.getException();
+            if (exception != null) {
+                throw new ServicesUnloadingException("service unload exception 
happened in enclave.", exception);
+            }
+        } finally {
+            getEnclaveContext().getEnclaveToken().restoreToken();
+        }
+    }
+
+    // it was called in service's proxy handler.
+    Object InvokeEnclaveMethod(EnclaveInvocationContext input) throws 
EnclaveMethodInvokingException {
+        if (!getEnclaveContext().getEnclaveToken().tryAcquireToken()) {
+            throw new EnclaveMethodInvokingException("enclave was destroyed.");
+        }
+        try {
+            byte[] payload;
+            try {
+                payload = SerializationHelper.serialize(input);
+            } catch (IOException e) {
+                throw new 
EnclaveMethodInvokingException("EnclaveInvokeMetaWrapper serialization 
failed.", e);
+            }
+            InnerNativeInvocationResult resultNativeWrapper = 
invokeMethodNative(payload);
+            if (resultNativeWrapper.getRet() != 0) {
+                throw new EnclaveMethodInvokingException("method invoke native 
call failed.");
+            }
+            EnclaveInvocationResult resultWrapper;
+            try {
+                resultWrapper = (EnclaveInvocationResult) 
SerializationHelper.deserialize(resultNativeWrapper.getPayload());
+            } catch (IOException | ClassNotFoundException e) {
+                throw new 
EnclaveMethodInvokingException("EnclaveInvokeResultWrapper deserialization 
failed.", e);
+            }
+            Throwable exception = resultWrapper.getException();
+            Object result = resultWrapper.getResult();
+            if (exception != null) {
+                EnclaveMethodInvokingException e = new 
EnclaveMethodInvokingException("method invoke exception happened in enclave.");
+                e.initCause(exception);
+                throw e;
+            }
+            return result;
+        } finally {
+            getEnclaveContext().getEnclaveToken().restoreToken();
+        }
+    }
+
+    @Override
+    public <T> Iterator<T> load(Class<T> service) throws 
ServicesLoadingException {
+        // Check service must be an interface class.
+        if (!service.isInterface()) {
+            throw new ServicesLoadingException("service type: " + 
service.getTypeName() + " is not an interface type.");
+        }
+
+        // If enclave type is MOCK_IN_JVM, loading services by JDK SPI 
mechanism directly.
+        if (enclaveContext.getEnclaveType() == EnclaveType.MOCK_IN_JVM) {
+            ServiceLoader<T> loader = ServiceLoader.load(service);
+            return loader.iterator();
+        }
+
+        // Loading services in enclave and creating proxy for them.
+        Class<?>[] serviceInterface = new Class[1];
+        serviceInterface[0] = service;
+
+        List<T> serviceProxies = new ArrayList<T>();
+        ServiceHandler[] services = loadService(service);
+        for (ServiceHandler serviceHandler : services) {
+            ProxyEnclaveInvocationHandler handler = new 
ProxyEnclaveInvocationHandler(this, serviceHandler);
+            T proxy = (T) Proxy.newProxyInstance(service.getClassLoader(), 
serviceInterface, handler);
+            serviceProxies.add(proxy);
+            // Register proxy handler for enclave's corresponding service gc 
recycling.
+            
enclaveContext.getEnclaveServicesRecycler().registerProxyHandler(handler);
+        }
+        return serviceProxies.iterator();
+    }
+
+    /**
+     * EnclaveContext cache an enclave's common information, such as
+     * enclave type and debug mode, and each enclave instance has a service
+     * resource recycle processor.
+     */
+    class EnclaveContext {
+        // enclave's type.
+        private final EnclaveType type;
+        // enclave's debug mode.
+        private final EnclaveDebug mode;
+        // every enclave has a services' recycler.
+        private final BaseEnclaveServicesRecycler enclaveServicesRecycler;
+        // every enclave has an enclave token.
+        private final EnclaveToken enclaveToken;
+
+        EnclaveContext(EnclaveType type,
+                       EnclaveDebug mode,
+                       BaseEnclaveServicesRecycler recycler) {
+            this.type = type;
+            this.mode = mode;
+            this.enclaveServicesRecycler = recycler;
+            this.enclaveToken = new EnclaveToken();
+        }
+
+        EnclaveType getEnclaveType() {
+            return type;
+        }
+
+        EnclaveDebug getEnclaveDebugMode() {
+            return mode;
+        }
+
+        BaseEnclaveServicesRecycler getEnclaveServicesRecycler() {
+            return enclaveServicesRecycler;
+        }
+
+        EnclaveToken getEnclaveToken() {
+            return enclaveToken;
+        }
+    }
+}
diff --git 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/BaseEnclaveServicesRecycler.java
 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/BaseEnclaveServicesRecycler.java
new file mode 100644
index 0000000..0b51196
--- /dev/null
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/BaseEnclaveServicesRecycler.java
@@ -0,0 +1,18 @@
+package com.alibaba.confidentialcomputing.host;
+
+/**
+ * BaseEnclaveServicesRecycler an empty enclave services recycler for 
MOCK_IN_JVM enclave.
+ */
+class BaseEnclaveServicesRecycler {
+    BaseEnclaveServicesRecycler() {
+    }
+
+    void enqueueProxyHandler(ProxyEnclaveInvocationHandler handler) {
+    }
+
+    void registerProxyHandler(ProxyEnclaveInvocationHandler handler) {
+    }
+
+    void interruptServiceRecycler() {
+    }
+}
diff --git 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/Enclave.java 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/Enclave.java
index e63541f..1baf92a 100644
--- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/Enclave.java
+++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/Enclave.java
@@ -58,7 +58,7 @@ public interface Enclave {
 
     /**
      * Returns all providers which implement service interface. It's similar 
to SPI
-     * ServiceLoader mechanism. It returns proxy providers which are mirrors 
to real
+     * ServiceLoader mechanism. It returns proxy providers which are handlers 
to real
      * services loaded in enclave.
      * <p>
      *
@@ -66,7 +66,7 @@ public interface Enclave {
      * @param service Must be a service interface
      * @return An iterator of providers were discovered.
      * @throws ServicesLoadingException {@link ServicesLoadingException} If 
proxy providers created
-     *                                  failed or mirrors services loaded 
failed in enclave.
+     *                                  failed or service handlers loaded 
failed in enclave.
      */
     <T> Iterator<T> load(Class<T> service) throws ServicesLoadingException;
 
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
new file mode 100644
index 0000000..208e4de
--- /dev/null
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveConfigure.java
@@ -0,0 +1,85 @@
+package com.alibaba.confidentialcomputing.host;
+
+import 
com.alibaba.confidentialcomputing.host.exception.EnclaveCreatingException;
+
+/**
+ * EnclaveConfigure decides a new created enclave's type and debug mode.
+ * If user creates an enclave with specific enclave type, that it is no
+ * matter what system variable is. If user creates an enclave with no
+ * specific enclave type, system variable is adapted to decide enclave's
+ * type and debug mode. Default enclave type is TEE_SDK and debug mode
+ * is RELEASE.
+ */
+class EnclaveConfigure {
+    private static final String ENCLAVE_TYPE = "com.alibaba.enclave.type";
+    private static final String ENCLAVE_DEBUG = "com.alibaba.enclave.debug";
+    private static final EnclaveType enclaveType;
+    private static final EnclaveDebug enclaveDebug;
+
+    static {
+        // Three kinds of enclave is supported, TEE_SDK/MOCK_IN_JVM/MOCK_IN_SVM
+        String platform = System.getProperty(ENCLAVE_TYPE);
+        String mode = System.getProperty(ENCLAVE_DEBUG);
+        if (platform != null) {
+            switch (platform) {
+                case "TEE_SDK":
+                    enclaveType = EnclaveType.TEE_SDK;
+                    break;
+                case "MOCK_IN_JVM":
+                    enclaveType = EnclaveType.MOCK_IN_JVM;
+                    break;
+                case "MOCK_IN_SVM":
+                    enclaveType = EnclaveType.MOCK_IN_SVM;
+                    break;
+                case "NONE":
+                default:
+                    enclaveType = EnclaveType.NONE;
+            }
+        } else {
+            // Default enclave type is tee sdk.
+            enclaveType = EnclaveType.TEE_SDK;
+        }
+
+        if (mode != null) {
+            // Three kinds of enclave debug mode is supported, DEBUG/RELEASE
+            // If TEE_SDK enclave is created as RELEASE mode, it can't be 
debugged
+            // with GDB tool.
+            switch (mode) {
+                case "DEBUG":
+                    enclaveDebug = EnclaveDebug.DEBUG;
+                    break;
+                case "RELEASE":
+                    enclaveDebug = EnclaveDebug.RELEASE;
+                    break;
+                case "NONE":
+                default:
+                    enclaveDebug = EnclaveDebug.NONE;
+            }
+        } else {
+            // Default debug mode is release.
+            enclaveDebug = EnclaveDebug.RELEASE;
+        }
+    }
+
+    // create an enclave without specific enclave type.
+    // if -Dcom.alibaba.enclave.type is not set, TEE_SDK
+    // type enclave will be created.
+    static Enclave create() throws EnclaveCreatingException {
+        return create(enclaveType);
+    }
+
+    // create an enclave with specific enclave type.
+    static Enclave create(EnclaveType type) throws EnclaveCreatingException {
+        switch (type) {
+            case MOCK_IN_JVM:
+                return new MockInJvmEnclave();
+            case MOCK_IN_SVM:
+                return new MockInSvmEnclave();
+            case TEE_SDK:
+                return new TeeSdkEnclave(enclaveDebug);
+            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
new file mode 100644
index 0000000..bf8ab83
--- /dev/null
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveDebug.java
@@ -0,0 +1,29 @@
+package com.alibaba.confidentialcomputing.host;
+
+/**
+ * An enumeration of enclave debug mode.
+ */
+enum EnclaveDebug {
+    /**
+     * 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.
+     */
+    DEBUG(1),
+    /**
+     * TEE_SDK could not debug by gdb tool in this mode.
+     */
+    RELEASE(2);
+
+    private final int value;
+
+    EnclaveDebug(int value) {
+        this.value = value;
+    }
+
+    int getValue() {
+        return value;
+    }
+}
diff --git 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveFactory.java
 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveFactory.java
index 9999de6..7df10f6 100644
--- 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveFactory.java
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveFactory.java
@@ -33,7 +33,7 @@ public final class EnclaveFactory {
      *                                  create failed.
      */
     public static Enclave create() throws EnclaveCreatingException {
-        return null;
+        return EnclaveConfigure.create();
     }
 
     /**
@@ -43,6 +43,6 @@ public final class EnclaveFactory {
      *                                  create failed.
      */
     public static Enclave create(EnclaveType type) throws 
EnclaveCreatingException {
-        return null;
+        return EnclaveConfigure.create(type);
     }
 }
\ No newline at end of file
diff --git 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveServicesRecycler.java
 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveServicesRecycler.java
new file mode 100644
index 0000000..13de12b
--- /dev/null
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveServicesRecycler.java
@@ -0,0 +1,62 @@
+package com.alibaba.confidentialcomputing.host;
+
+import 
com.alibaba.confidentialcomputing.host.exception.ServicesUnloadingException;
+
+import java.lang.ref.Cleaner;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/**
+ * EnclaveServicesRecycler is responsible for an enclave's services resource 
recycling.
+ * If a service handler in host side was recycled by gc, 
EnclaveServicesRecycle will help
+ * to recycle the corresponding service loaded in enclave side.
+ * EnclaveServicesRecycle starts a new thread to recycle enclave's services 
asynchronously.
+ */
+class EnclaveServicesRecycler extends BaseEnclaveServicesRecycler {
+    private final Cleaner cleaner = Cleaner.create();
+    // toBeReleasedEnclaveServices stores a service proxy handler when it's 
recycled
+    // by gc in host side.
+    private final BlockingQueue<ProxyEnclaveInvocationHandler> 
toBeReleasedEnclaveServices = new LinkedBlockingQueue<>();
+    private final Thread recyclerThread;
+
+    EnclaveServicesRecycler() {
+        recyclerThread = new Thread(() -> {
+            while (!Thread.interrupted()) {
+                try {
+                    ProxyEnclaveInvocationHandler proxyHandler = 
toBeReleasedEnclaveServices.take();
+                    
proxyHandler.getEnclave().unloadService(proxyHandler.getServiceHandler());
+                } catch (InterruptedException e) {
+                    break; // Recycle Thread should exit when enclave 
destroyed.
+                } catch (ServicesUnloadingException e) {
+                    // Have to handle this exception locally, print to log 
later.
+                    e.printStackTrace();
+                }
+            }
+        });
+        recyclerThread.setDaemon(true);
+        recyclerThread.start();
+    }
+
+    // enqueue the recycled proxy handler object of a service handler.
+    @Override
+    void enqueueProxyHandler(ProxyEnclaveInvocationHandler handler) {
+        try {
+            toBeReleasedEnclaveServices.add(handler);
+        } catch (IllegalStateException | ClassCastException | 
NullPointerException | IllegalArgumentException e) {
+            // Have to handle this exception locally.
+            e.printStackTrace();
+        }
+    }
+
+    // register service's proxy handler when it's created.
+    @Override
+    void registerProxyHandler(ProxyEnclaveInvocationHandler handler) {
+        cleaner.register(handler, handler);
+    }
+
+    // interrupt enclave services' recycler thread exit.
+    @Override
+    void interruptServiceRecycler() {
+        recyclerThread.interrupt();
+    }
+}
diff --git 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveToken.java
 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveToken.java
new file mode 100644
index 0000000..7d54dc0
--- /dev/null
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveToken.java
@@ -0,0 +1,46 @@
+package com.alibaba.confidentialcomputing.host;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * EnclaveToken avoids an enclave's invocation happen when it's being 
destroyed.
+ */
+class EnclaveToken {
+    private volatile AtomicBoolean alive = new AtomicBoolean(true);
+    private final int MAX_CONCURRENCY_INVOKER = 999999;
+    private final Semaphore tokens = new Semaphore(MAX_CONCURRENCY_INVOKER);
+
+    /**
+     * tryAcquireToken try to get an enclave's token.
+     */
+    boolean tryAcquireToken() {
+        if (alive.get()) {
+            return tokens.tryAcquire();
+        }
+        return false;
+    }
+
+    /**
+     * restoreToken restores the enclave token.
+     */
+    void restoreToken() {
+        tokens.release();
+    }
+
+    /**
+     * destroyToken prevents an enclave invocation and waits for all
+     * ongoing enclave invocations finished.
+     */
+    boolean destroyToken() {
+        if (alive.compareAndSet(true, false)) {
+            try {
+                tokens.acquire(MAX_CONCURRENCY_INVOKER);
+            } catch (InterruptedException e) {
+                ; // Should never happen, do nothing here.
+            }
+            return true;
+        }
+        return false;
+    }
+}
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
new file mode 100644
index 0000000..84fc41b
--- /dev/null
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ExtractLibrary.java
@@ -0,0 +1,34 @@
+package com.alibaba.confidentialcomputing.host;
+
+import java.io.*;
+
+/**
+ * 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.
+ */
+public final class ExtractLibrary {
+    /**
+     * get the temp file's full path.
+     *
+     * @param classLoader define the search scope for lib .so.
+     * @param name        lib.so's name in the jar file.
+     * @return the temp file's full path.
+     */
+    public static String extractLibrary(ClassLoader classLoader, String name) 
throws IOException {
+        int pos = name.lastIndexOf('.');
+        File file = File.createTempFile(name.substring(0, pos), 
name.substring(pos));
+        String fullPath = file.getAbsolutePath();
+        try (InputStream in = classLoader.getResourceAsStream(name);
+             OutputStream out = new FileOutputStream(file)) {
+            byte[] buf = new byte[4096];
+            int length;
+            while ((length = in.read(buf)) > 0) {
+                out.write(buf, 0, length);
+            }
+        } finally {
+            file.deleteOnExit();
+        }
+        return fullPath;
+    }
+}
diff --git 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/InnerNativeInvocationResult.java
 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/InnerNativeInvocationResult.java
new file mode 100644
index 0000000..6e8e240
--- /dev/null
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/InnerNativeInvocationResult.java
@@ -0,0 +1,27 @@
+package com.alibaba.confidentialcomputing.host;
+
+/**
+ * InnerNativeInvocationResult is load_service unload_service and invoke_method
+ * native call's return value. It not only contains enclave e_call's return 
value,
+ * also contains an EnclaveInvocationResult object's serialization payload from
+ * method invocation in enclave.
+ */
+class InnerNativeInvocationResult {
+    // enclave method native call's result.
+    private final int ret;
+    // payload is an EnclaveInvocationResult object's serialization data.
+    private final byte[] payload;
+
+    InnerNativeInvocationResult(int ret, byte[] payload) {
+        this.ret = ret;
+        this.payload = payload;
+    }
+
+    int getRet() {
+        return ret;
+    }
+
+    byte[] getPayload() {
+        return payload;
+    }
+}
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
new file mode 100644
index 0000000..faa0a87
--- /dev/null
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockInJvmEnclave.java
@@ -0,0 +1,32 @@
+package com.alibaba.confidentialcomputing.host;
+
+/**
+ * MockInJvmEnclave is a mock jvm enclave. Both host and enclave codes run
+ * in one jvm. It was used for test and debug.
+ */
+class MockInJvmEnclave extends AbstractEnclave {
+    MockInJvmEnclave() {
+        // Set EnclaveContext for this enclave instance.
+        super(EnclaveType.MOCK_IN_JVM, new BaseEnclaveServicesRecycler());
+    }
+
+    @Override
+    InnerNativeInvocationResult loadServiceNative(byte[] payload) {
+        return null;
+    }
+
+    @Override
+    InnerNativeInvocationResult unloadServiceNative(byte[] payload) {
+        return null;
+    }
+
+    @Override
+    InnerNativeInvocationResult invokeMethodNative(byte[] payload) {
+        return null;
+    }
+
+    @Override
+    public void destroy() {
+        ; // Do nothing here.
+    }
+}
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
new file mode 100644
index 0000000..84e4618
--- /dev/null
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockInSvmEnclave.java
@@ -0,0 +1,214 @@
+package com.alibaba.confidentialcomputing.host;
+
+import 
com.alibaba.confidentialcomputing.host.exception.EnclaveCreatingException;
+import 
com.alibaba.confidentialcomputing.host.exception.EnclaveDestroyingException;
+
+import java.io.IOException;
+
+/**
+ * MockInSvmEnclave is a mock svm enclave. Host part code runs in jvm and 
enclave
+ * part code was compiled into native image, we could view enclave part as a 
service
+ * provider, and all service invocation will be implemented in enclave by 
reflection.
+ * The work mechanism in this mode is very closed to tee sdk enclave, so it's 
very
+ * important to debug issue.
+ */
+class MockInSvmEnclave extends AbstractEnclave {
+    private final static String JNI_EXTRACTED_PACKAGE_PATH = 
"jni/lib_jni_mock_svm.so";
+    private final static String ENCLAVE_SVM_WRAPPER_PACKAGE_PATH = 
"libs/lib_enclave_mock_svm_wrapper.so";
+    private final static String ENCLAVE_SVM_PACKAGE_PATH = 
"libs/lib_svm_sdk.so";
+    private static volatile MockInSvmExtractTempPath extractTempPath;
+    private final EnclaveNativeContextCache nativeHandlerContext = new 
EnclaveNativeContextCache(
+            0, 0, 0, 0);
+
+    MockInSvmEnclave() throws EnclaveCreatingException {
+        // Set EnclaveContext for this enclave instance.
+        super(EnclaveType.MOCK_IN_SVM, new EnclaveServicesRecycler());
+
+        // Extract jni .so and svm sdk .so from .jar file.
+        if (extractTempPath == null) {
+            synchronized (MockInSvmEnclave.class) {
+                if (extractTempPath == null) {
+                    try {
+                        String jniTempFilePath = ExtractLibrary.extractLibrary(
+                                MockInSvmEnclave.class.getClassLoader(),
+                                JNI_EXTRACTED_PACKAGE_PATH);
+                        String enclaveWrapperFilePath = 
ExtractLibrary.extractLibrary(
+                                MockInSvmEnclave.class.getClassLoader(),
+                                ENCLAVE_SVM_WRAPPER_PACKAGE_PATH);
+                        String enclaveSvmFilePath = 
ExtractLibrary.extractLibrary(
+                                MockInSvmEnclave.class.getClassLoader(),
+                                ENCLAVE_SVM_PACKAGE_PATH);
+                        extractTempPath = new 
MockInSvmEnclave.MockInSvmExtractTempPath(
+                                jniTempFilePath,
+                                enclaveWrapperFilePath,
+                                enclaveSvmFilePath);
+                        System.load(jniTempFilePath);
+                    } catch (IOException e) {
+                        throw new EnclaveCreatingException("extracting tee sdk 
jni .so or signed .so failed.", e);
+                    }
+                }
+            }
+        }
+
+        // Create svm sdk enclave by native call, enclaveWrapperHandle and 
enclaveSvmSdkHandle are set in jni in nativeHandlerContext.
+        int ret = nativeCreateEnclave(extractTempPath.getJniTempFilePath());
+        if (ret != 0) {
+            throw new EnclaveCreatingException("create svm sdk enclave by 
native calling failed.");
+        }
+        // Create svm attach isolate and isolateThread, and they are set in 
jni in nativeHandlerContext.
+        ret = 
nativeSvmAttachIsolate(nativeHandlerContext.getEnclaveWrapperHandle(),
+                nativeHandlerContext.getEnclaveSvmSdkHandle());
+        if (ret != 0) {
+            throw new EnclaveCreatingException("create svm isolate by native 
calling failed.");
+        }
+    }
+
+    @Override
+    InnerNativeInvocationResult loadServiceNative(byte[] payload) {
+        return nativeLoadService(
+                nativeHandlerContext.getEnclaveWrapperHandle(),
+                nativeHandlerContext.getEnclaveSvmSdkHandle(),
+                nativeHandlerContext.getIsolateHandle(),
+                payload);
+    }
+
+    @Override
+    InnerNativeInvocationResult unloadServiceNative(byte[] payload) {
+        return nativeUnloadService(
+                nativeHandlerContext.getEnclaveWrapperHandle(),
+                nativeHandlerContext.getEnclaveSvmSdkHandle(),
+                nativeHandlerContext.getIsolateHandle(),
+                payload);
+    }
+
+    @Override
+    InnerNativeInvocationResult invokeMethodNative(byte[] payload) {
+        return nativeInvokeMethod(
+                nativeHandlerContext.getEnclaveWrapperHandle(),
+                nativeHandlerContext.getEnclaveSvmSdkHandle(),
+                nativeHandlerContext.getIsolateHandle(),
+                payload);
+    }
+
+    @Override
+    public void destroy() throws EnclaveDestroyingException {
+        // destroyToken will wait for all ongoing enclave invocations finished.
+        if (this.getEnclaveContext().getEnclaveToken().destroyToken()) {
+            // interrupt enclave services' recycler firstly.
+            
this.getEnclaveContext().getEnclaveServicesRecycler().interruptServiceRecycler();
+            // destroy svm isolate.
+            int ret = nativeSvmDetachIsolate(
+                    nativeHandlerContext.getEnclaveWrapperHandle(),
+                    nativeHandlerContext.getEnclaveSvmSdkHandle(),
+                    nativeHandlerContext.getIsolateThreadHandle());
+            if (ret != 0) {
+                throw new EnclaveDestroyingException("isolate destroy native 
call failed.");
+            }
+            ret = nativeDestroyEnclave(
+                    nativeHandlerContext.getEnclaveWrapperHandle(),
+                    nativeHandlerContext.getEnclaveSvmSdkHandle());
+            if (ret != 0) {
+                throw new EnclaveDestroyingException("enclave destroy native 
call failed.");
+            }
+        }
+
+    }
+
+    private native int nativeCreateEnclave(String path);
+
+    private native int nativeSvmAttachIsolate(
+            long enclaveWrapperHandle,
+            long enclaveSvmSdkHandle);
+
+    private native InnerNativeInvocationResult nativeLoadService(
+            long enclaveWrapperHandle,
+            long enclaveSvmSdkHandle,
+            long isolateHandler,
+            byte[] serviceHandler);
+
+    private native InnerNativeInvocationResult nativeInvokeMethod(
+            long enclaveWrapperHandle,
+            long enclaveSvmSdkHandle,
+            long isolateHandler,
+            byte[] enclaveInvokeMetaWrapper);
+
+    private native InnerNativeInvocationResult nativeUnloadService(
+            long enclaveWrapperHandle,
+            long enclaveSvmSdkHandle,
+            long isolateHandler,
+            byte[] serviceHandler);
+
+    private native int nativeSvmDetachIsolate(
+            long enclaveWrapperHandle,
+            long enclaveSvmSdkHandle,
+            long isolateThreadHandler);
+
+    private native int nativeDestroyEnclave(
+            long enclaveWrapperHandle,
+            long enclaveSvmSdkHandle);
+
+    /**
+     * JavaEnclave will create svm isolate handle and isolateThread handle by 
native call,
+     * so EnclaveNativeContextCache will cache them for usage.
+     */
+    class EnclaveNativeContextCache {
+        // enclaveHandle stores created enclave wrap .so file handler.
+        private final long enclaveWrapperHandle;
+        // enclaveHandle stores created enclave svm sdk .so file handler.
+        private final long enclaveSvmSdkHandle;
+        // isolate stores svm created isolate instance.
+        // In JavaEnclave only one isolateHandle instance will be created.
+        private final long isolateHandle;
+        // isolateThreadHandle stores the first attached isolateThread Handle.
+        private final long isolateThreadHandle;
+
+        EnclaveNativeContextCache(
+                long enclaveWrapperHandle, long enclaveSvmSdkHandle,
+                long isolateHandle, long isolateThreadHandle) {
+            this.enclaveWrapperHandle = enclaveWrapperHandle;
+            this.enclaveSvmSdkHandle = enclaveSvmSdkHandle;
+            this.isolateHandle = isolateHandle;
+            this.isolateThreadHandle = isolateThreadHandle;
+        }
+
+        long getEnclaveWrapperHandle() {
+            return enclaveWrapperHandle;
+        }
+
+        long getEnclaveSvmSdkHandle() {
+            return enclaveSvmSdkHandle;
+        }
+
+        long getIsolateHandle() {
+            return isolateHandle;
+        }
+
+        long getIsolateThreadHandle() {
+            return isolateThreadHandle;
+        }
+    }
+
+    class MockInSvmExtractTempPath {
+        private final String jniTempFilePath;
+        private final String enclaveWrapperFilePath;
+        private final String enclaveSvmFilePath;
+
+        MockInSvmExtractTempPath(String jniTempFilePath, String 
enclaveWrapperFilePath, String enclaveSvmFilePath) {
+            this.jniTempFilePath = jniTempFilePath;
+            this.enclaveWrapperFilePath = enclaveWrapperFilePath;
+            this.enclaveSvmFilePath = enclaveSvmFilePath;
+        }
+
+        String getJniTempFilePath() {
+            return jniTempFilePath;
+        }
+
+        String getEnclaveWrapperFilePath() {
+            return enclaveWrapperFilePath;
+        }
+
+        String getEnclaveSvmFilePath() {
+            return enclaveSvmFilePath;
+        }
+    }
+}
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
new file mode 100644
index 0000000..65eb630
--- /dev/null
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ProxyEnclaveInvocationHandler.java
@@ -0,0 +1,87 @@
+package com.alibaba.confidentialcomputing.host;
+
+import com.alibaba.confidentialcomputing.common.EnclaveInvocationContext;
+import com.alibaba.confidentialcomputing.common.ServiceHandler;
+import 
com.alibaba.confidentialcomputing.host.exception.EnclaveMethodInvokingException;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+/**
+ * ProxyEnclaveInvocationHandler define a service's proxy invocation handler.
+ */
+class ProxyEnclaveInvocationHandler implements InvocationHandler, Runnable {
+    private final AbstractEnclave enclave;
+    private final ServiceHandler serviceHandler;
+
+    ProxyEnclaveInvocationHandler(AbstractEnclave enclave, ServiceHandler 
serviceHandler) {
+        this.enclave = enclave;
+        this.serviceHandler = serviceHandler;
+    }
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws 
Throwable {
+        EnclaveInvocationContext methodInvokeMetaWrapper;
+        String[] parameterTypes;
+        // Building a method wrapper for enclave native invocation.
+        if (args != null) {
+            parameterTypes = new String[args.length];
+            // Get a method's parameter type exactly.
+            Class<?>[] paraTypes = method.getParameterTypes();
+            for (int index = 0x0; index < args.length; index++) {
+                parameterTypes[index] = paraTypes[index].getName();
+            }
+            methodInvokeMetaWrapper = new EnclaveInvocationContext(
+                    serviceHandler,
+                    method.getName(),
+                    parameterTypes,
+                    args);
+        } else {
+            methodInvokeMetaWrapper = new EnclaveInvocationContext(
+                    serviceHandler,
+                    method.getName(), null, null);
+        }
+
+        // Handle service method invocation exception.
+        Object result;
+        try {
+            result = enclave.InvokeEnclaveMethod(methodInvokeMetaWrapper);
+        } catch (EnclaveMethodInvokingException e) {
+            // Get cause exception if it has one.
+            Throwable cause = e.getCause();
+            Class<?>[] exceptionTypes = method.getExceptionTypes();
+            if (cause != null && cause 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.
+                for (Class<?> exception : exceptionTypes) {
+                    if (exception == cause.getCause().getClass()) {
+                        throw cause.getCause();
+                    }
+                }
+            }
+            throw e;
+        }
+        return result;
+    }
+
+    AbstractEnclave getEnclave() {
+        return enclave;
+    }
+
+    ServiceHandler getServiceHandler() {
+        return serviceHandler;
+    }
+
+    // If a proxy handler object was recycled by gc in host side, tell 
EnclaveServicesRecycle to
+    // recycle the corresponding service loaded in enclave.
+    @Override
+    public void run() {
+        
enclave.getEnclaveContext().getEnclaveServicesRecycler().enqueueProxyHandler(this);
+    }
+}
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
new file mode 100644
index 0000000..e7ee41e
--- /dev/null
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkEnclave.java
@@ -0,0 +1,164 @@
+package com.alibaba.confidentialcomputing.host;
+
+import com.alibaba.confidentialcomputing.host.exception.*;
+
+import java.io.IOException;
+
+/**
+ * TeeSdkEnclave is a sgx2 enclave based on Alibaba cloud's tee sdk.
+ */
+class TeeSdkEnclave extends AbstractEnclave {
+    private final static String JNI_EXTRACTED_PACKAGE_PATH = 
"jni/lib_jni_tee_sdk.so";
+    private final static String TEE_SDK_SIGNED_PACKAGE_PATH = 
"libs/lib_enclave_tee_sdk.signed";
+    private static volatile TeeSdkExtractTempPath extractTempPath;
+    private final EnclaveNativeContext nativeHandlerContext = new 
EnclaveNativeContext(
+            0, 0, 0);
+
+    TeeSdkEnclave(EnclaveDebug mode) throws EnclaveCreatingException {
+        // Set EnclaveContext for this enclave instance.
+        super(EnclaveType.TEE_SDK, mode, new EnclaveServicesRecycler());
+
+        // Extract jni .so and signed tee .so from .jar file.
+        // Only once extract and load operation.
+        if (extractTempPath == null) {
+            synchronized (TeeSdkEnclave.class) {
+                if (extractTempPath == null) {
+                    try {
+                        String jniTempFilePath = ExtractLibrary.extractLibrary(
+                                TeeSdkEnclave.class.getClassLoader(),
+                                JNI_EXTRACTED_PACKAGE_PATH);
+                        String teeSdkSignedFilePath = 
ExtractLibrary.extractLibrary(
+                                TeeSdkEnclave.class.getClassLoader(),
+                                TEE_SDK_SIGNED_PACKAGE_PATH);
+                        extractTempPath = new 
TeeSdkExtractTempPath(jniTempFilePath, teeSdkSignedFilePath);
+                        System.load(jniTempFilePath);
+                    } catch (IOException e) {
+                        throw new EnclaveCreatingException("extracting tee sdk 
jni .so or signed .so failed.", e);
+                    }
+                }
+            }
+        }
+
+        // Create tee sdk enclave by native call, enclaveHandler is set in jni 
in nativeHandlerContext.
+        int ret = nativeCreateEnclave(mode.getValue(), 
extractTempPath.getTeeSdkSignedFilePath());
+        if (ret != 0) {
+            throw new EnclaveCreatingException("create tee sdk enclave by 
native calling failed.");
+        }
+        // Create svm attach isolate and isolateThread, and they are set in 
jni in nativeHandlerContext.
+        ret = nativeSvmAttachIsolate(nativeHandlerContext.getEnclaveHandle());
+        if (ret != 0) {
+            throw new EnclaveCreatingException("create svm isolate by native 
calling failed.");
+        }
+    }
+
+    private native int nativeCreateEnclave(int mode, String path);
+
+    private native int nativeSvmAttachIsolate(long enclaveHandler);
+
+    private native InnerNativeInvocationResult nativeLoadService(
+            long enclaveHandler, long isolateHandler, byte[] serviceHandler);
+
+    private native InnerNativeInvocationResult nativeInvokeMethod(
+            long enclaveHandler, long isolateHandler, byte[] 
enclaveInvokeMetaWrapper);
+
+    private native InnerNativeInvocationResult nativeUnloadService(
+            long enclaveHandler, long isolateHandler, byte[] serviceHandler);
+
+    private native int nativeSvmDetachIsolate(long enclaveHandler, long 
isolateThreadHandler);
+
+    private native int nativeDestroyEnclave(long enclaveHandler);
+
+    @Override
+    InnerNativeInvocationResult loadServiceNative(byte[] payload) {
+        return nativeLoadService(
+                nativeHandlerContext.getEnclaveHandle(),
+                nativeHandlerContext.getIsolateHandle(),
+                payload);
+    }
+
+    @Override
+    InnerNativeInvocationResult unloadServiceNative(byte[] payload) {
+        return nativeUnloadService(
+                nativeHandlerContext.getEnclaveHandle(),
+                nativeHandlerContext.getIsolateHandle(),
+                payload);
+    }
+
+    @Override
+    InnerNativeInvocationResult invokeMethodNative(byte[] payload) {
+        return nativeInvokeMethod(
+                nativeHandlerContext.getEnclaveHandle(),
+                nativeHandlerContext.getIsolateHandle(),
+                payload);
+    }
+
+    @Override
+    public void destroy() throws EnclaveDestroyingException {
+        // destroyToken will wait for all ongoing enclave invocations finished.
+        if (this.getEnclaveContext().getEnclaveToken().destroyToken()) {
+            // interrupt enclave services' recycler firstly.
+            
this.getEnclaveContext().getEnclaveServicesRecycler().interruptServiceRecycler();
+            // destroy svm isolate.
+            int ret = 
nativeSvmDetachIsolate(nativeHandlerContext.getEnclaveHandle(),
+                    nativeHandlerContext.getIsolateThreadHandle());
+            if (ret != 0) {
+                throw new EnclaveDestroyingException("isolate destroy native 
call failed.");
+            }
+            // destroy the enclave.
+            ret = 
nativeDestroyEnclave(nativeHandlerContext.getEnclaveHandle());
+            if (ret != 0) {
+                throw new EnclaveDestroyingException("enclave destroy native 
call failed.");
+            }
+        }
+    }
+
+    class TeeSdkExtractTempPath {
+        private final String jniTempFilePath;
+        private final String teeSdkSignedFilePath;
+
+        TeeSdkExtractTempPath(String jniTempFilePath, String 
teeSdkSignedFilePath) {
+            this.jniTempFilePath = jniTempFilePath;
+            this.teeSdkSignedFilePath = teeSdkSignedFilePath;
+        }
+
+        String getJniTempFilePath() {
+            return jniTempFilePath;
+        }
+
+        String getTeeSdkSignedFilePath() {
+            return teeSdkSignedFilePath;
+        }
+    }
+
+    /**
+     * JavaEnclave will create svm isolate handle and isolateThread handle by 
native call,
+     * so EnclaveNativeContextCache will cache them for usage.
+     */
+    class EnclaveNativeContext {
+        // enclaveHandle stores created enclave's handle id.
+        private final long enclaveHandle;
+        // isolate stores svm created isolate instance.
+        // In JavaEnclave only one isolateHandle instance will be created.
+        private final long isolateHandle;
+        // isolateThreadHandle stores the first attached isolateThread Handle.
+        private final long isolateThreadHandle;
+
+        EnclaveNativeContext(long enclaveHandle, long isolateHandle, long 
isolateThreadHandle) {
+            this.enclaveHandle = enclaveHandle;
+            this.isolateHandle = isolateHandle;
+            this.isolateThreadHandle = isolateThreadHandle;
+        }
+
+        long getEnclaveHandle() {
+            return enclaveHandle;
+        }
+
+        long getIsolateHandle() {
+            return isolateHandle;
+        }
+
+        long getIsolateThreadHandle() {
+            return isolateThreadHandle;
+        }
+    }
+}
diff --git 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/ConfidentialComputingException.java
 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/ConfidentialComputingException.java
index 3bedccf..f7af01a 100644
--- 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/ConfidentialComputingException.java
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/ConfidentialComputingException.java
@@ -20,4 +20,56 @@ public class ConfidentialComputingException extends 
Exception {
     public ConfidentialComputingException(Throwable e) {
         super(e);
     }
+
+    /**
+     * @param info exception message.
+     * @param e    exception.
+     */
+    public ConfidentialComputingException(String info, Throwable e) {
+        super(info, e);
+    }
+
+    /**
+     * EnclaveNativeInvokingException defines all kinds of possible exceptions 
towards an
+     * enclave's native operation. Basically there are two kinds error about 
enclave operation,
+     * one kind is native calling return an unexpected value, the other kind 
is an exception
+     * happen in enclave and transform into host side. If a native invoking 
into enclave returns
+     * an error value, enum of EnclaveNativeInvokingException will add extra 
error message details
+     * for debugging; If an exception happened in enclave and transformed to 
host side, it will be
+     * thrown again in host side to user.
+     * Programmers need to handle EnclaveNativeInvokingException seriously.
+     */
+    enum EnclaveNativeInvokingException {
+        // Enclave creating failed.
+        ENCLAVE_CREATING_ERROR("A0001", "creating enclave failed."),
+        // Enclave destroying failed.
+        ENCLAVE_DESTROYING_ERROR("A0002", "destroying enclave failed"),
+        // Services loading failed.
+        SERVICES_LOADING_ERROR("A0003", "services loading failed in enclave"),
+        // Services unloading failed.
+        SERVICES_UNLOADING_ERROR("A0004", "service unloading failed in 
enclave"),
+        // Service method invoking failed.
+        SERVICE_METHOD_INVOKING_ERROR("A0005", "service method invoking 
failed");
+
+        private final String errorCode;
+        private final String errorMessage;
+
+        EnclaveNativeInvokingException(String errorCode, String errorMessage) {
+            this.errorCode = errorCode;
+            this.errorMessage = errorMessage;
+        }
+
+        String buildExceptionMessage(String details) {
+            if (details != null) {
+                return this.toString() + " DetailErrorMessage: " + details;
+            } else {
+                return this.toString();
+            }
+        }
+
+        @Override
+        public String toString() {
+            return "ErrorCode: " + this.errorCode + " , " + " ErrorMessage: " 
+ this.errorMessage;
+        }
+    }
 }
\ No newline at end of file
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 82cda63..cfbdd99 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
@@ -10,13 +10,21 @@ public class EnclaveCreatingException extends 
ConfidentialComputingException {
      * @param info exception information.
      */
     public EnclaveCreatingException(String info) {
-        super(info);
+        
super(EnclaveNativeInvokingException.ENCLAVE_CREATING_ERROR.buildExceptionMessage(info));
     }
 
     /**
      * @param e exception.
      */
     public EnclaveCreatingException(Throwable e) {
-        super(e);
+        
super(EnclaveNativeInvokingException.ENCLAVE_CREATING_ERROR.toString(), e);
+    }
+
+    /**
+     * @param info exception message.
+     * @param e    exception.
+     */
+    public EnclaveCreatingException(String info, Throwable e) {
+        
super(EnclaveNativeInvokingException.ENCLAVE_CREATING_ERROR.buildExceptionMessage(info),
 e);
     }
 }
\ No newline at end of file
diff --git 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/EnclaveDestroyingException.java
 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/EnclaveDestroyingException.java
index e83aedf..c46b1d5 100644
--- 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/EnclaveDestroyingException.java
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/EnclaveDestroyingException.java
@@ -10,13 +10,21 @@ public class EnclaveDestroyingException extends 
ConfidentialComputingException {
      * @param info exception information.
      */
     public EnclaveDestroyingException(String info) {
-        super(info);
+        
super(EnclaveNativeInvokingException.ENCLAVE_DESTROYING_ERROR.buildExceptionMessage(info));
     }
 
     /**
      * @param e exception.
      */
     public EnclaveDestroyingException(Throwable e) {
-        super(e);
+        
super(EnclaveNativeInvokingException.ENCLAVE_DESTROYING_ERROR.toString(), e);
+    }
+
+    /**
+     * @param info exception message.
+     * @param e    exception.
+     */
+    public EnclaveDestroyingException(String info, Throwable e) {
+        
super(EnclaveNativeInvokingException.ENCLAVE_DESTROYING_ERROR.buildExceptionMessage(info),
 e);
     }
 }
\ No newline at end of file
diff --git 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/EnclaveMethodInvokingException.java
 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/EnclaveMethodInvokingException.java
new file mode 100644
index 0000000..fcb534b
--- /dev/null
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/EnclaveMethodInvokingException.java
@@ -0,0 +1,30 @@
+package com.alibaba.confidentialcomputing.host.exception;
+
+/**
+ * EnclaveMethodInvokingException {@link EnclaveMethodInvokingException} is 
thrown when exception happen
+ * during an enclave's method was invoking.
+ * Programmers need to handle EnclaveInvokeException seriously.
+ */
+public class EnclaveMethodInvokingException extends 
ConfidentialComputingException {
+    /**
+     * @param info exception information.
+     */
+    public EnclaveMethodInvokingException(String info) {
+        
super(EnclaveNativeInvokingException.SERVICE_METHOD_INVOKING_ERROR.buildExceptionMessage(info));
+    }
+
+    /**
+     * @param e exception.
+     */
+    public EnclaveMethodInvokingException(Throwable e) {
+        
super(EnclaveNativeInvokingException.SERVICE_METHOD_INVOKING_ERROR.toString(), 
e);
+    }
+
+    /**
+     * @param info exception message.
+     * @param e    exception.
+     */
+    public EnclaveMethodInvokingException(String info, Throwable e) {
+        
super(EnclaveNativeInvokingException.SERVICE_METHOD_INVOKING_ERROR.buildExceptionMessage(info),
 e);
+    }
+}
diff --git 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/ServicesLoadingException.java
 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/ServicesLoadingException.java
index dfb187c..7fda291 100644
--- 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/ServicesLoadingException.java
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/ServicesLoadingException.java
@@ -10,13 +10,21 @@ public class ServicesLoadingException extends 
ConfidentialComputingException {
      * @param info exception information.
      */
     public ServicesLoadingException(String info) {
-        super(info);
+        
super(EnclaveNativeInvokingException.SERVICES_LOADING_ERROR.buildExceptionMessage(info));
     }
 
     /**
      * @param e exception.
      */
     public ServicesLoadingException(Throwable e) {
-        super(e);
+        
super(EnclaveNativeInvokingException.SERVICES_LOADING_ERROR.toString(), e);
+    }
+
+    /**
+     * @param info exception info.
+     * @param e    exception.
+     */
+    public ServicesLoadingException(String info, Throwable e) {
+        
super(EnclaveNativeInvokingException.SERVICES_LOADING_ERROR.buildExceptionMessage(info),
 e);
     }
 }
\ No newline at end of file
diff --git 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/ServicesUnloadingException.java
 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/ServicesUnloadingException.java
new file mode 100644
index 0000000..4c0de9d
--- /dev/null
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/ServicesUnloadingException.java
@@ -0,0 +1,30 @@
+package com.alibaba.confidentialcomputing.host.exception;
+
+/**
+ * ServicesUnloadingException {@link ServicesUnloadingException} is thrown 
when exception happen
+ * during an enclave's service was unloading.
+ * Programmers need to handle UnloadServiceException seriously.
+ */
+public class ServicesUnloadingException extends ConfidentialComputingException 
{
+    /**
+     * @param info exception information.
+     */
+    public ServicesUnloadingException(String info) {
+        
super(EnclaveNativeInvokingException.SERVICES_UNLOADING_ERROR.buildExceptionMessage(info));
+    }
+
+    /**
+     * @param e exception.
+     */
+    public ServicesUnloadingException(Throwable e) {
+        
super(EnclaveNativeInvokingException.SERVICES_UNLOADING_ERROR.toString(), e);
+    }
+
+    /**
+     * @param info exception info.
+     * @param e    exception.
+     */
+    public ServicesUnloadingException(String info, Throwable e) {
+        
super(EnclaveNativeInvokingException.SERVICES_UNLOADING_ERROR.buildExceptionMessage(info),
 e);
+    }
+}
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
new file mode 100644
index 0000000..e1a9b34
--- /dev/null
+++ 
b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/MockTestEnclave.java
@@ -0,0 +1,166 @@
+package com.alibaba.confidentialcomputing.host;
+
+import com.alibaba.confidentialcomputing.common.*;
+import 
com.alibaba.confidentialcomputing.host.exception.EnclaveCreatingException;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+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<>();
+    private static final Queue<ServiceHandler> cacheServiceHandler = new 
LinkedList<>();
+
+    MockTestEnclave() throws EnclaveCreatingException {
+        super(EnclaveType.NONE, EnclaveDebug.NONE, new 
BaseEnclaveServicesRecycler());
+    }
+
+    private static Class<?>[] parseParamClass(String[] parameterTypes) {
+        if (parameterTypes == null) {
+            return null;
+        }
+        List<Class<?>> parametersClass = new ArrayList<>();
+        Arrays.stream(parameterTypes).forEach(p -> {
+            try {
+                parametersClass.add(nameToType(p));
+            } catch (ClassNotFoundException e) {
+                assertTrue(false);
+            }
+        });
+        return parametersClass.toArray(new Class<?>[0]);
+    }
+
+    private static Class<?> nameToType(String name) throws 
ClassNotFoundException {
+        if (name.indexOf('.') == -1) {
+            switch (name) {
+                case "boolean":
+                    return boolean.class;
+                case "char":
+                    return char.class;
+                case "float":
+                    return float.class;
+                case "double":
+                    return double.class;
+                case "byte":
+                    return byte.class;
+                case "short":
+                    return short.class;
+                case "int":
+                    return int.class;
+                case "long":
+                    return long.class;
+                case "void":
+                    return void.class;
+            }
+        }
+        return Class.forName(name);
+    }
+
+    @Override
+    InnerNativeInvocationResult loadServiceNative(byte[] payload) {
+        EnclaveInvocationContext invocationContext;
+        List<ServiceHandler> handlers = new ArrayList<>();
+        Throwable exception = null;
+        EnclaveInvocationResult result;
+        try {
+            invocationContext = (EnclaveInvocationContext) 
SerializationHelper.deserialize(payload);
+            String interfaceName = 
invocationContext.getServiceHandler().getServiceInterfaceName();
+            Class<?> service = Class.forName(interfaceName);
+            Iterator<?> services = ServiceLoader.load(service).iterator();
+            while (services.hasNext()) {
+                String identity = 
String.valueOf(instanceIdentity.addAndGet(1));
+                Object instance = services.next();
+                ServiceHandler sm = new ServiceHandler(interfaceName, 
instance.getClass().getName(), identity);
+                handlers.add(sm);
+                cacheServiceHandler.add(sm);
+                instancesRegisterCenter.put(identity, instance);
+            }
+        } catch (IOException | ClassNotFoundException e) {
+            exception = e;
+        } finally {
+            result = new EnclaveInvocationResult(handlers.toArray(new 
ServiceHandler[0]), exception);
+        }
+
+        try {
+            return new InnerNativeInvocationResult(0, 
SerializationHelper.serialize(result));
+        } catch (IOException e) {
+            return new InnerNativeInvocationResult(-1, null);
+        }
+    }
+
+    @Override
+    InnerNativeInvocationResult unloadServiceNative(byte[] payload) {
+        EnclaveInvocationContext invocationContext;
+        Throwable exception = null;
+        EnclaveInvocationResult result;
+        try {
+            invocationContext = (EnclaveInvocationContext) 
SerializationHelper.deserialize(payload);
+            
instancesRegisterCenter.remove(invocationContext.getServiceHandler().getInstanceIdentity());
+        } catch (IOException | ClassNotFoundException e) {
+            exception = e;
+        } finally {
+            result = new EnclaveInvocationResult(null, exception);
+        }
+
+        try {
+            return new InnerNativeInvocationResult(0, 
SerializationHelper.serialize(result));
+        } catch (IOException e) {
+            return new InnerNativeInvocationResult(-1, null);
+        }
+    }
+
+    @Override
+    InnerNativeInvocationResult invokeMethodNative(byte[] payload) {
+        EnclaveInvocationContext invocationContext;
+        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();
+            Object[] args = invocationContext.getArguments();
+            Object instance = 
instancesRegisterCenter.get(invocationContext.getServiceHandler().getInstanceIdentity());
+            assertNotNull(instance);
+            assertTrue(className.equals(instance.getClass().getName()));
+            Class<?> service = Class.forName(className);
+            Method method = service.getDeclaredMethod(methodName, 
parseParamClass(parameterTypes));
+            method.setAccessible(true);
+            invokeRet = method.invoke(instance, args);
+        } catch (Throwable e) {
+            exception = e;
+        } finally {
+            result = new EnclaveInvocationResult(invokeRet, exception);
+        }
+
+        try {
+            return new InnerNativeInvocationResult(0, 
SerializationHelper.serialize(result));
+        } catch (IOException e) {
+            return new InnerNativeInvocationResult(-1, null);
+        }
+    }
+
+    @Override
+    public void destroy() {
+        // destroyToken will wait for all ongoing enclave invocations finished.
+        if (this.getEnclaveContext().getEnclaveToken().destroyToken()) {
+            // interrupt enclave services' recycler firstly.
+            
this.getEnclaveContext().getEnclaveServicesRecycler().interruptServiceRecycler();
+        }
+    }
+
+    int getServicesNum() {
+        return instancesRegisterCenter.size();
+    }
+
+    Queue<?> getCachedServiceHandler() {
+        return cacheServiceHandler;
+    }
+}
\ No newline at end of file
diff --git 
a/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/Service.java 
b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/Service.java
new file mode 100644
index 0000000..13842ad
--- /dev/null
+++ b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/Service.java
@@ -0,0 +1,11 @@
+package com.alibaba.confidentialcomputing.host;
+
+public interface Service {
+    void doNothing();
+
+    int add(int a, int b);
+
+    String saySomething(String words);
+
+    void throwException(String code) throws ServiceExceptionTest;
+}
diff --git 
a/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/ServiceExceptionTest.java
 
b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/ServiceExceptionTest.java
new file mode 100644
index 0000000..753f793
--- /dev/null
+++ 
b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/ServiceExceptionTest.java
@@ -0,0 +1,7 @@
+package com.alibaba.confidentialcomputing.host;
+
+public class ServiceExceptionTest extends Exception {
+    public ServiceExceptionTest(String info) {
+        super(info);
+    }
+}
diff --git 
a/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/ServiceImpl.java
 
b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/ServiceImpl.java
new file mode 100644
index 0000000..b364b9e
--- /dev/null
+++ 
b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/ServiceImpl.java
@@ -0,0 +1,26 @@
+package com.alibaba.confidentialcomputing.host;
+
+import com.google.auto.service.AutoService;
+
+@AutoService(Service.class)
+public class ServiceImpl implements Service {
+    @Override
+    public void doNothing() {
+        ; // Do nothing;
+    }
+
+    @Override
+    public int add(int a, int b) {
+        return a + b;
+    }
+
+    @Override
+    public String saySomething(String words) {
+        return words;
+    }
+
+    @Override
+    public void throwException(String code) throws ServiceExceptionTest {
+        throw new ServiceExceptionTest(code);
+    }
+}
diff --git 
a/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/TestAbstractEnclave.java
 
b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/TestAbstractEnclave.java
new file mode 100644
index 0000000..a66aca7
--- /dev/null
+++ 
b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/TestAbstractEnclave.java
@@ -0,0 +1,46 @@
+package com.alibaba.confidentialcomputing.host;
+
+import com.alibaba.confidentialcomputing.common.ServiceHandler;
+import 
com.alibaba.confidentialcomputing.host.exception.EnclaveCreatingException;
+import 
com.alibaba.confidentialcomputing.host.exception.EnclaveMethodInvokingException;
+import 
com.alibaba.confidentialcomputing.host.exception.ServicesLoadingException;
+import org.junit.jupiter.api.*;
+
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.Iterator;
+import java.util.Queue;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class TestAbstractEnclave {
+    private static Enclave enclave;
+
+    @BeforeAll
+    static void create() throws EnclaveCreatingException {
+        enclave = new MockTestEnclave();
+    }
+
+    @Test
+    void testEnclave() throws Exception {
+        Iterator<?> services = enclave.load(Service.class);
+        assertEquals(1, ((MockTestEnclave) enclave).getServicesNum());
+        assertNotNull(services);
+        assertTrue(services.hasNext());
+        Service service = (Service) services.next();
+        service.doNothing();
+        assertEquals(200, service.add(20, 180));
+        assertTrue("Hello World".equals(service.saySomething("Hello World")));
+        assertThrows(ServiceExceptionTest.class, () -> 
service.throwException("something is wrong"));
+        Queue<?> queue = ((MockTestEnclave) enclave).getCachedServiceHandler();
+        assertEquals(1, queue.size());
+        ((MockTestEnclave) enclave).unloadService((ServiceHandler) 
queue.poll());
+        assertEquals(0, ((MockTestEnclave) enclave).getServicesNum());
+        enclave.destroy();
+        assertThrows(ServicesLoadingException.class, () -> 
enclave.load(Service.class));
+        try {
+            service.doNothing();
+        } catch (UndeclaredThrowableException e) {
+            assertEquals(e.getCause().getClass(), 
EnclaveMethodInvokingException.class);
+        }
+    }
+}
diff --git 
a/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/TestEnclaveFactory.java
 
b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/TestEnclaveFactory.java
new file mode 100644
index 0000000..410ece9
--- /dev/null
+++ 
b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/TestEnclaveFactory.java
@@ -0,0 +1,16 @@
+package com.alibaba.confidentialcomputing.host;
+
+import 
com.alibaba.confidentialcomputing.host.exception.EnclaveCreatingException;
+import 
com.alibaba.confidentialcomputing.host.exception.EnclaveDestroyingException;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class TestEnclaveFactory {
+    @Test
+    void testEnclaveCreate() throws EnclaveCreatingException, 
EnclaveDestroyingException {
+        Enclave enclave = EnclaveFactory.create(EnclaveType.MOCK_IN_JVM);
+        assertTrue(enclave instanceof MockInJvmEnclave);
+        enclave.destroy();
+    }
+}
diff --git a/sdk/pom.xml b/sdk/pom.xml
index 24f2a05..3d93a44 100644
--- a/sdk/pom.xml
+++ b/sdk/pom.xml
@@ -13,6 +13,11 @@
     </properties>
     <dependencyManagement>
         <dependencies>
+            <dependency>
+                <groupId>com.alibaba.confidentialcomputing</groupId>
+                <artifactId>common</artifactId>
+                <version>0.1.0</version>
+            </dependency>
             <dependency>
                 <groupId>com.alibaba.confidentialcomputing</groupId>
                 <artifactId>enclave</artifactId>
@@ -29,16 +34,35 @@
                 <version>0.8.3</version>
                 <scope>test</scope>
             </dependency>
+            <dependency>
+                <groupId>org.junit.jupiter</groupId>
+                <artifactId>junit-jupiter-api</artifactId>
+                <version>5.7.1</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.junit.platform</groupId>
+                <artifactId>junit-platform-engine</artifactId>
+                <version>1.8.2</version>
+                <scope>test</scope>
+            </dependency>
             <dependency>
                 <groupId>org.junit.jupiter</groupId>
                 <artifactId>junit-jupiter-engine</artifactId>
-                <version>5.4.0</version>
+                <version>5.6.2</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.junit-pioneer</groupId>
+                <artifactId>junit-pioneer</artifactId>
+                <version>1.5.0</version>
                 <scope>test</scope>
             </dependency>
         </dependencies>
     </dependencyManagement>
     <modules>
+        <module>common</module>
         <module>enclave</module>
         <module>host</module>
     </modules>
-</project>
\ No newline at end of file
+</project>


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to