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 c74f1f3353f2e3c922b60e486155f7870e4822ad
Author: jeffery.wsj <[email protected]>
AuthorDate: Mon Aug 8 04:50:07 2022 +0800

    [sdk] Support JavaEnclave benchmark metric tracing feature
    
    Summary:
    1. Add metric tracing feature for JavaEnclave.
    2. Add metric tracing unit test case.
    3. Add sm2/sm3/sm4 test case based on bouncycastle.
    
    Test Plan: all tests pass
    
    Reviewers: lei.yul, cengfeng.lzy, sanhong.lsh
    
    Issue: https://aone.alibaba-inc.com/task/43916112
    
    CR: 
https://code.aone.alibaba-inc.com/java-tee/JavaEnclave/codereview/9697539
---
 build.sh                                           |   4 +
 .../com/alibaba/samples/helloworld/host/Main.java  |   5 +-
 .../common/EnclaveInvocationResult.java            |  18 +++
 .../enclave/InvocationWrapper.java                 |   2 +
 .../enclave/agent/EnclaveAgentServiceImpl.java     |  44 +++----
 .../enclave/framework/LoadServiceInvoker.java      |   3 +-
 .../tee_sdk_svm/edge_routines/tee_sdk_symbol.c     |   8 +-
 .../host/AbstractEnclave.java                      | 132 ++++++++++++---------
 .../host/BaseEnclaveServicesRecycler.java          |   6 +-
 .../host/EmbeddedLibOSEnclave.java                 |  10 +-
 .../host/EnclaveConfigure.java                     |  54 +++++----
 .../confidentialcomputing/host/EnclaveInfo.java    |   5 +
 .../host/EnclaveServicesRecycler.java              |   9 +-
 .../confidentialcomputing/host/MetricTrace.java    |  76 ++++++++++++
 .../host/MetricTraceContext.java                   |  62 ++++++++++
 .../host/MockEnclaveInfo.java                      |   7 ++
 .../host/MockInJvmEnclave.java                     |  12 +-
 .../host/MockInSvmEnclave.java                     |  19 +--
 .../host/ProxyEnclaveInvocationHandler.java        |  20 ++--
 .../host/ProxyMockJvmInvocationHandler.java        |  48 ++++++++
 .../confidentialcomputing/host/SGXEnclaveInfo.java |   7 ++
 .../confidentialcomputing/host/TeeSdkEnclave.java  |  21 ++--
 .../exception/MetricTraceLogWriteException.java    |  30 +++++
 .../host/TestRemoteAttestation.java                |   3 +-
 sdk/native/script/build_app/Makefile               |  11 +-
 .../test/common/MetricTraceService.java            |   8 ++
 .../test/common/SM2Service.java                    |   8 ++
 .../test/common/SM3Service.java                    |   8 ++
 .../test/common/SM4Service.java                    |   8 ++
 test/enclave/pom.xml                               |  25 ++++
 .../test/enclave/MetricTraceServiceImpl.java       |  17 +++
 .../test/enclave/SM2ServiceImpl.java               |  91 ++++++++++++++
 .../test/enclave/SM3ServiceImpl.java               |  19 +++
 .../test/enclave/SM4ServiceImpl.java               |  57 +++++++++
 .../test/host/TestEnclaveMetricTrace.java          |  67 +++++++++++
 .../test/host/TestSMEnclave.java                   |  91 ++++++++++++++
 test/pom.xml                                       |  13 +-
 tools/cicd/Dockerfile                              |   4 +-
 tools/cicd/make.sh                                 |   6 +-
 39 files changed, 884 insertions(+), 154 deletions(-)

diff --git a/build.sh b/build.sh
index fc270bc..e6338da 100755
--- a/build.sh
+++ b/build.sh
@@ -21,5 +21,9 @@ cd "${WORKDIR}"/sdk && mvn $SETTING clean install
 # Install JavaEnclave SDK
 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
+# Install JavaEnclave archetype
+cd "${WORKDIR}"/archetype && mvn $SETTING clean install
+# Install BouncyCastle Native Package
+cd "${WORKDIR}"/third-party-libs/bouncycastle-native && mvn $SETTING clean 
install
 # Test unit test cases in JavaEnclave
 cd "${WORKDIR}"/test && OCCLUM_RELEASE_ENCLAVE=true mvn $SETTING -Pnative 
clean package
diff --git 
a/samples/helloworld/host/src/main/java/com/alibaba/samples/helloworld/host/Main.java
 
b/samples/helloworld/host/src/main/java/com/alibaba/samples/helloworld/host/Main.java
index d531358..c8d3784 100644
--- 
a/samples/helloworld/host/src/main/java/com/alibaba/samples/helloworld/host/Main.java
+++ 
b/samples/helloworld/host/src/main/java/com/alibaba/samples/helloworld/host/Main.java
@@ -3,15 +3,12 @@ package com.alibaba.samples.helloworld.host;
 import com.alibaba.confidentialcomputing.host.Enclave;
 import com.alibaba.confidentialcomputing.host.EnclaveFactory;
 import com.alibaba.confidentialcomputing.host.EnclaveType;
-import 
com.alibaba.confidentialcomputing.host.exception.EnclaveCreatingException;
-import 
com.alibaba.confidentialcomputing.host.exception.EnclaveDestroyingException;
-import 
com.alibaba.confidentialcomputing.host.exception.ServicesLoadingException;
 import com.alibaba.samples.helloworld.common.Service;
 
 import java.util.Iterator;
 
 public class Main {
-    public static void main(String[] args) throws EnclaveCreatingException, 
ServicesLoadingException, EnclaveDestroyingException {
+    public static void main(String[] args) throws Exception {
         EnclaveType[] enclaveTypes = {
                 EnclaveType.MOCK_IN_JVM,
                 EnclaveType.MOCK_IN_SVM,
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
index b664304..aea12e1 100644
--- 
a/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EnclaveInvocationResult.java
+++ 
b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EnclaveInvocationResult.java
@@ -15,6 +15,7 @@ public final class EnclaveInvocationResult implements 
Serializable {
 
     private final Object resultedValue;
     private final Throwable exception;
+    private long cost; // ns.
 
     public EnclaveInvocationResult(Object result, Throwable exception) {
         this.resultedValue = result;
@@ -38,4 +39,21 @@ public final class EnclaveInvocationResult implements 
Serializable {
     public Throwable getException() {
         return this.exception;
     }
+
+    /**
+     * set method's overhead.
+     *
+     */
+    public void setCost(long cost) {
+        this.cost = cost;
+    }
+
+    /**
+     * get method's overhead.
+     *
+     * @return method's overhead(ns).
+     */
+    public long getCost() {
+        return this.cost;
+    }
 }
\ No newline at end of file
diff --git 
a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/InvocationWrapper.java
 
b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/InvocationWrapper.java
index 98b5eb6..cb8ff24 100644
--- 
a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/InvocationWrapper.java
+++ 
b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/InvocationWrapper.java
@@ -23,6 +23,7 @@ import java.io.IOException;
 public class InvocationWrapper {
 
     public static <T> void invoke(EncData input, EncData result, CallBacks 
callBacks, EnclaveMethodInvoker<T> invoker) throws IOException {
+        long start = System.nanoTime();
         byte[] data = transformInput(input);
         EnclaveInvocationResult ret;
         try {
@@ -31,6 +32,7 @@ public class InvocationWrapper {
             ret = new EnclaveInvocationResult(null, new 
ConfidentialComputingException(t));
         }
         // Set method returned value to result parameter
+        ret.setCost(System.nanoTime() - start);
         wrapReturnValue(result, callBacks, ret);
     }
 
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
index b5e5716..f396873 100644
--- 
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
@@ -6,6 +6,7 @@ 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.EnclaveMethodInvoker;
 import com.alibaba.confidentialcomputing.enclave.framework.LoadServiceInvoker;
 import 
com.alibaba.confidentialcomputing.enclave.framework.ServiceMethodInvoker;
 import 
com.alibaba.confidentialcomputing.enclave.framework.UnloadServiceInvoker;
@@ -20,40 +21,32 @@ public class EnclaveAgentServiceImpl {
     protected EnclaveAgentServiceImpl() {
     }
 
-    public byte[] loadService(String serviceName) {
+    private <T> byte[] invoke(EnclaveMethodInvoker<T> invoker, T input) {
+        long start = System.nanoTime();
+        EnclaveInvocationResult ret;
         try {
-            return 
SerializationHelper.serialize(loadServiceInstance.callMethod(serviceName));
-        } catch (IOException e) {
-            try {
-                return SerializationHelper.serialize(new 
EnclaveInvocationResult(null, e));
-            } catch (IOException ex) {
-            }
+            ret = invoker.callMethod(input);
+        } catch (Throwable t) {
+            ret = new EnclaveInvocationResult(null, new 
ConfidentialComputingException(t));
+        }
+        ret.setCost(System.nanoTime() - start);
+        try {
+            return SerializationHelper.serialize(ret);
+        } catch (IOException ex) {
         }
         return null;
     }
 
+    public byte[] loadService(String serviceName) {
+        return invoke(loadServiceInstance, serviceName);
+    }
+
     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;
+        return invoke(unloadServiceInstance, handler);
     }
 
     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;
+        return invoke(serviceInvokerInstance, context);
     }
 
     public byte[] generateAttestationReport(byte[] userDate) {
@@ -64,6 +57,7 @@ public class EnclaveAgentServiceImpl {
         } catch (ConfidentialComputingException e) {
             exception = e;
         }
+
         try {
             return SerializationHelper.serialize(new 
EnclaveInvocationResult(report, exception));
         } catch (IOException e) {
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 a4b2dec..fe6f6b7 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
@@ -14,9 +14,8 @@ public final class LoadServiceInvoker implements 
EnclaveMethodInvoker<String> {
      */
     @Override
     public EnclaveInvocationResult callMethod(String inputData) {
-        Class<?> service;
         try {
-            service = Class.forName(inputData);
+            Class<?> service = Class.forName(inputData);
             return new 
EnclaveInvocationResult(EnclaveContext.getInstance().loadService(service), 
null);
         } catch (ClassNotFoundException e) {
             return new EnclaveInvocationResult(null, e);
diff --git 
a/sdk/enclave/src/main/native/cpp/platform/tee_sdk_svm/edge_routines/tee_sdk_symbol.c
 
b/sdk/enclave/src/main/native/cpp/platform/tee_sdk_svm/edge_routines/tee_sdk_symbol.c
index 0a74027..d5e7ce8 100644
--- 
a/sdk/enclave/src/main/native/cpp/platform/tee_sdk_svm/edge_routines/tee_sdk_symbol.c
+++ 
b/sdk/enclave/src/main/native/cpp/platform/tee_sdk_svm/edge_routines/tee_sdk_symbol.c
@@ -66,7 +66,7 @@ char* strcat(char* dest, const char* source) {
        return dest;
 }
 
-char* strcpy(char* dest,const char* sourse) {
+char* strcpy(char* dest, const char* sourse) {
     TRACE_SYMBOL_CALL();
     if(dest==NULL || sourse==NULL) return NULL;
     char* res=dest;
@@ -74,10 +74,10 @@ char* strcpy(char* dest,const char* sourse) {
     return res;
 }
 
-char* stpcpy(char *dest, const char *src) {
+char* stpcpy(char *dest, const char *sourse) {
     TRACE_SYMBOL_CALL();
-    size_t len = strlen (src);
-    return memcpy(dest, src, len + 1) + len;
+    strcpy(dest, sourse);
+    return dest + strlen(sourse);
 }
 
 size_t __getdelim(char **lineptr, size_t *n, int delim, FILE *stream) {
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 87af3ed..30142a3 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
@@ -11,11 +11,7 @@ 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.RemoteAttestationException;
-import 
com.alibaba.confidentialcomputing.host.exception.ServicesLoadingException;
-import 
com.alibaba.confidentialcomputing.host.exception.ServicesUnloadingException;
+import com.alibaba.confidentialcomputing.host.exception.*;
 
 /**
  * AbstractEnclave implements all kinds of enclave platform's common operation.
@@ -54,20 +50,48 @@ abstract class AbstractEnclave implements Enclave {
 
     abstract AttestationReport generateAttestationReportNative(byte[] 
userData) throws RemoteAttestationException;
 
-    // load service by interface name.
-    ServiceHandler[] loadService(Class<?> service) throws 
ServicesLoadingException {
+    // load service by interface name in mock_jvm mode.
+    // because mock_svm/tee_sdk/lib_os adopt serialization and deserialization 
between host and enclave,
+    // while mock_jvm will call enclave service directly.
+    <T> Iterator<T> loadProxyServiceMockJVM(Class<?> service) throws 
ServicesLoadingException {
+        try (MetricTraceContext trace = new MetricTraceContext(
+                this.getEnclaveInfo(),
+                
MetricTraceContext.LogPrefix.METRIC_LOG_ENCLAVE_SERVICE_LOADING_PATTERN,
+                service.getName())) {
+            List<T> serviceProxies = new ArrayList<>();
+            Class<?>[] serviceInterface = new Class[]{service};
+
+            ServiceLoader<T> innerProxyServices = (ServiceLoader<T>) 
ServiceLoader.load(service);
+            for (T innerProxyService : innerProxyServices) {
+                ProxyMockJvmInvocationHandler handler = new 
ProxyMockJvmInvocationHandler(this, innerProxyService);
+                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(proxy, 
handler);
+            }
+            return serviceProxies.iterator();
+        } catch (MetricTraceLogWriteException e) {
+            throw new ServicesLoadingException(e);
+        }
+    }
+
+    // load service by interface name in mock_svm/tee_sdk/lib_os enclave mode.
+    <T> Iterator<T> loadProxyService(Class<?> service) throws 
ServicesLoadingException {
         if (!getEnclaveContext().getEnclaveToken().tryAcquireToken()) {
             throw new ServicesLoadingException("enclave was destroyed.");
         }
-        try {
+        try (MetricTraceContext trace = new MetricTraceContext(
+                this.getEnclaveInfo(),
+                
MetricTraceContext.LogPrefix.METRIC_LOG_ENCLAVE_SERVICE_LOADING_PATTERN,
+                service.getName())) {
+            List<T> serviceProxies = new ArrayList<>();
+            Class<?>[] serviceInterface = new Class[]{service};
+
             // Only need to provide service's interface name is enough to load 
service
             // in enclave.
             EnclaveInvocationResult resultWrapper;
-            try {
-                resultWrapper = (EnclaveInvocationResult) 
SerializationHelper.deserialize(loadServiceNative(service.getName()));
-            } catch (IOException | ClassNotFoundException e) {
-                throw new ServicesLoadingException("EnclaveInvokeResultWrapper 
deserialization failed.", e);
-            }
+            resultWrapper = (EnclaveInvocationResult) 
SerializationHelper.deserialize(loadServiceNative(service.getName()));
+            trace.setCostInnerEnclave(resultWrapper.getCost());
             Throwable exception = resultWrapper.getException();
             Object result = resultWrapper.getResult();
             // this exception is transformed from enclave, so throw it and 
handle it in proxy handler.
@@ -81,7 +105,19 @@ abstract class AbstractEnclave implements Enclave {
             if (!(result instanceof ServiceHandler[])) {
                 throw new ServicesLoadingException("service load return type 
is not ServiceHandler[].");
             }
-            return (ServiceHandler[]) result;
+
+            for (ServiceHandler serviceHandler : (ServiceHandler[]) result) {
+                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(proxy, 
handler);
+            }
+            return serviceProxies.iterator();
+        } catch (IOException | ClassNotFoundException e) {
+            throw new ServicesLoadingException("EnclaveInvokeResultWrapper 
deserialization failed.", e);
+        } catch (MetricTraceLogWriteException e) {
+            throw new ServicesLoadingException(e);
         } finally {
             getEnclaveContext().getEnclaveToken().restoreToken();
         }
@@ -93,41 +129,37 @@ abstract class AbstractEnclave implements Enclave {
         if (!getEnclaveContext().getEnclaveToken().tryAcquireToken()) {
             throw new ServicesUnloadingException("enclave was destroyed.");
         }
-        try {
+        try (MetricTraceContext trace = new MetricTraceContext(
+                this.getEnclaveInfo(),
+                
MetricTraceContext.LogPrefix.METRIC_LOG_ENCLAVE_SERVICE_UNLOADING_PATTERN,
+                service.getServiceImplClassName())) {
             EnclaveInvocationResult resultWrapper;
-            try {
-                resultWrapper = (EnclaveInvocationResult) 
SerializationHelper.deserialize(unloadServiceNative(service));
-            } catch (IOException | ClassNotFoundException e) {
-                throw new 
ServicesUnloadingException("EnclaveInvokeResultWrapper deserialization 
failed.", e);
-            }
+            resultWrapper = (EnclaveInvocationResult) 
SerializationHelper.deserialize(unloadServiceNative(service));
+            trace.setCostInnerEnclave(resultWrapper.getCost());
             Throwable exception = resultWrapper.getException();
             if (exception != null) {
                 throw new ServicesUnloadingException("service unload exception 
happened in enclave.", exception);
             }
+        } catch (IOException | ClassNotFoundException e) {
+            throw new ServicesUnloadingException("EnclaveInvokeResultWrapper 
deserialization failed.", e);
+        } catch (MetricTraceLogWriteException e) {
+            throw new ServicesUnloadingException(e);
         } finally {
             getEnclaveContext().getEnclaveToken().restoreToken();
         }
     }
 
     // it was called in service's proxy handler.
-    Object InvokeEnclaveMethod(EnclaveInvocationContext input) throws 
EnclaveMethodInvokingException {
+    EnclaveInvocationResult InvokeEnclaveMethod(EnclaveInvocationContext 
input) throws EnclaveMethodInvokingException {
         if (!getEnclaveContext().getEnclaveToken().tryAcquireToken()) {
             throw new EnclaveMethodInvokingException("enclave was destroyed.");
         }
         try {
             EnclaveInvocationResult resultWrapper;
-            try {
-                resultWrapper = (EnclaveInvocationResult) 
SerializationHelper.deserialize(invokeMethodNative(input));
-            } catch (IOException | ClassNotFoundException e) {
-                throw new 
EnclaveMethodInvokingException("EnclaveInvokeResultWrapper deserialization 
failed.", e);
-            }
-            Throwable exception = resultWrapper.getException();
-            if (exception != null) {
-                EnclaveMethodInvokingException e = new 
EnclaveMethodInvokingException("method invoke exception happened in enclave.");
-                e.initCause(exception);
-                throw e;
-            }
-            return resultWrapper.getResult();
+            resultWrapper = (EnclaveInvocationResult) 
SerializationHelper.deserialize(invokeMethodNative(input));
+            return resultWrapper;
+        } catch (IOException | ClassNotFoundException e) {
+            throw new 
EnclaveMethodInvokingException("EnclaveInvokeResultWrapper deserialization 
failed.", e);
         } finally {
             getEnclaveContext().getEnclaveToken().restoreToken();
         }
@@ -151,26 +183,20 @@ abstract class AbstractEnclave implements Enclave {
             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<>();
-        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(proxy, 
handler);
-        }
-        return serviceProxies.iterator();
+        Iterator<T> serviceProxies;
+        switch (enclaveContext.getEnclaveType()) {
+            // If enclave type is MOCK_IN_JVM, loading services by JDK SPI 
mechanism directly.
+            case MOCK_IN_JVM:
+                serviceProxies = loadProxyServiceMockJVM(service);
+                break;
+            // Loading services in enclave and creating proxy for them.
+            case MOCK_IN_SVM:
+            case TEE_SDK:
+            case EMBEDDED_LIB_OS:
+            default:
+                serviceProxies = loadProxyService(service);
+        }
+        return serviceProxies;
     }
 
     /**
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
index 957539e..e323c3d 100644
--- 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/BaseEnclaveServicesRecycler.java
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/BaseEnclaveServicesRecycler.java
@@ -1,5 +1,7 @@
 package com.alibaba.confidentialcomputing.host;
 
+import java.lang.reflect.InvocationHandler;
+
 /**
  * BaseEnclaveServicesRecycler an empty enclave services recycler for 
MOCK_IN_JVM enclave.
  */
@@ -7,10 +9,10 @@ class BaseEnclaveServicesRecycler {
     BaseEnclaveServicesRecycler() {
     }
 
-    void enqueueProxyHandler(ProxyEnclaveInvocationHandler handler) {
+    void enqueueProxyHandler(InvocationHandler handler) {
     }
 
-    void registerProxyHandler(Object obj, ProxyEnclaveInvocationHandler 
handler) {
+    void registerProxyHandler(Object obj, InvocationHandler handler) {
     }
 
     void interruptServiceRecycler() {
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
index c44b403..0c6a9c0 100644
--- 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclave.java
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclave.java
@@ -15,8 +15,8 @@ import com.alibaba.confidentialcomputing.host.exception.*;
  * 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_CONNECT_TIMEOUT_MS = 800; // ms.
+    private static final int HTTP_READ_TIMEOUT_MS = 2000;   // 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:";;
@@ -241,6 +241,12 @@ public class EmbeddedLibOSEnclave extends AbstractEnclave {
             // 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.
+            try (MetricTraceContext trace = new MetricTraceContext(
+                    this.getEnclaveInfo(),
+                    
MetricTraceContext.LogPrefix.METRIC_LOG_ENCLAVE_DESTROYING_PATTERN)) {
+            } catch (MetricTraceLogWriteException e) {
+                throw new EnclaveDestroyingException(e);
+            }
         }
     }
 
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 30086e8..00d4201 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
@@ -1,6 +1,9 @@
 package com.alibaba.confidentialcomputing.host;
 
 import 
com.alibaba.confidentialcomputing.host.exception.EnclaveCreatingException;
+import 
com.alibaba.confidentialcomputing.host.exception.MetricTraceLogWriteException;
+
+import java.io.IOException;
 
 /**
  * EnclaveConfigure decides a new created enclave's type and debug mode.
@@ -73,29 +76,34 @@ class EnclaveConfigure {
 
     // create an enclave with specific enclave type.
     static Enclave create(EnclaveType type) throws EnclaveCreatingException {
-        Enclave enclave;
-        switch (type) {
-            case MOCK_IN_JVM:
-                enclave = new MockInJvmEnclave();
-                break;
-            case MOCK_IN_SVM:
-                enclave = new MockInSvmEnclave();
-                break;
-            case TEE_SDK:
-                // TEE_SDK only support hardware mode, not support simulate 
mode.
-                enclave = new TeeSdkEnclave(enclaveDebug);
-                break;
-            case EMBEDDED_LIB_OS:
-                // EMBEDDED_LIB_OS only support hardware mode, not support 
simulate mode.
-                enclave = EmbeddedLibOSEnclave.getEmbeddedLibOSEnclaveInstance(
-                        
EmbeddedLibOSEnclaveConfig.getEmbeddedLibOSEnclaveConfigInstance().getDebuggable(),
-                        EnclaveSimulate.HARDWARE);
-                break;
-            case NONE:
-            default:
-                throw new EnclaveCreatingException("enclave type is not 
supported.");
+        try (MetricTraceContext trace = new 
MetricTraceContext(MetricTraceContext.LogPrefix.METRIC_LOG_ENCLAVE_CREATING_PATTERN))
 {
+            Enclave enclave;
+            switch (type) {
+                case MOCK_IN_JVM:
+                    enclave = new MockInJvmEnclave();
+                    break;
+                case MOCK_IN_SVM:
+                    enclave = new MockInSvmEnclave();
+                    break;
+                case TEE_SDK:
+                    // TEE_SDK only support hardware mode, not support 
simulate mode.
+                    enclave = new TeeSdkEnclave(enclaveDebug);
+                    break;
+                case EMBEDDED_LIB_OS:
+                    // EMBEDDED_LIB_OS only support hardware mode, not support 
simulate mode.
+                    enclave = 
EmbeddedLibOSEnclave.getEmbeddedLibOSEnclaveInstance(
+                            
EmbeddedLibOSEnclaveConfig.getEmbeddedLibOSEnclaveConfigInstance().getDebuggable(),
+                            EnclaveSimulate.HARDWARE);
+                    break;
+                case NONE:
+                default:
+                    throw new EnclaveCreatingException("enclave type is not 
supported.");
+            }
+            trace.setEnclaveInfo(enclave.getEnclaveInfo());
+            
EnclaveInfoManager.getEnclaveInfoManagerInstance().addEnclave(enclave);
+            return enclave;
+        } catch (IOException | MetricTraceLogWriteException e) {
+            throw new EnclaveCreatingException(e);
         }
-        EnclaveInfoManager.getEnclaveInfoManagerInstance().addEnclave(enclave);
-        return enclave;
     }
 }
diff --git 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveInfo.java
 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveInfo.java
index 1eaa9f5..a66d324 100644
--- 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveInfo.java
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveInfo.java
@@ -9,6 +9,11 @@ public interface EnclaveInfo {
      */
     EnclaveType getEnclaveType();
 
+    /**
+     * the enclave's Hash ID.
+     */
+    int getEnclaveID();
+
     /**
      * is the enclave debuggable or not. MOCK_IN_JVM and MOCK_IN_SVM are 
simulation mode,
      * so the two mock enclave type are debuggable. TEE_SDK and 
EMBEDDED_LIB_OS depend on
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
index 711c0b7..7af0ad4 100644
--- 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveServicesRecycler.java
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveServicesRecycler.java
@@ -3,6 +3,7 @@ package com.alibaba.confidentialcomputing.host;
 import 
com.alibaba.confidentialcomputing.host.exception.ServicesUnloadingException;
 
 import java.lang.ref.Cleaner;
+import java.lang.reflect.InvocationHandler;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
 
@@ -39,9 +40,9 @@ class EnclaveServicesRecycler extends 
BaseEnclaveServicesRecycler {
 
     // enqueue the recycled proxy handler object of a service handler.
     @Override
-    void enqueueProxyHandler(ProxyEnclaveInvocationHandler handler) {
+    void enqueueProxyHandler(InvocationHandler handler) {
         try {
-            toBeReleasedEnclaveServices.add(handler);
+            toBeReleasedEnclaveServices.add((ProxyEnclaveInvocationHandler) 
handler);
         } catch (IllegalStateException | ClassCastException | 
NullPointerException | IllegalArgumentException e) {
             // Have to handle this exception locally.
             e.printStackTrace();
@@ -50,8 +51,8 @@ class EnclaveServicesRecycler extends 
BaseEnclaveServicesRecycler {
 
     // register service's proxy handler when it's created.
     @Override
-    void registerProxyHandler(Object obj, ProxyEnclaveInvocationHandler 
handler) {
-        cleaner.register(obj, handler);
+    void registerProxyHandler(Object obj, InvocationHandler handler) {
+        cleaner.register(obj, (ProxyEnclaveInvocationHandler)handler);
     }
 
     // interrupt enclave services' recycler thread exit.
diff --git 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MetricTrace.java
 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MetricTrace.java
new file mode 100644
index 0000000..afb9ca2
--- /dev/null
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MetricTrace.java
@@ -0,0 +1,76 @@
+package com.alibaba.confidentialcomputing.host;
+
+import 
com.alibaba.confidentialcomputing.host.exception.MetricTraceLogWriteException;
+
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.text.DecimalFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+public abstract class MetricTrace implements AutoCloseable {
+    private final static String PRIORITY_METRIC_LOG_PATH = 
"com.alibaba.enclave.metric.path";
+    private final static String PRIORITY_ENABLE_METRIC_LOG = 
"com.alibaba.enclave.metric.on";
+
+    private static boolean enableEnclaveMetricTrace = false;
+    private final static String DEFAULT_METRIC_LOG_PATH =
+            "JavaEnclave_Metric_Log_" + new SimpleDateFormat("yyyy-MM-dd 
HH:mm:ss").format(new Date()) + ".log";
+    private static volatile String logPath;
+    private static volatile BufferedWriter logFile;
+    private static DecimalFormat formatter = new DecimalFormat("###,###");
+
+    private final long start = System.nanoTime();
+
+    static {
+        String metricLogFlag = System.getProperty(PRIORITY_ENABLE_METRIC_LOG);
+        if ("true".equals(metricLogFlag) || "1".equals(metricLogFlag)) {
+            enableEnclaveMetricTrace = true;
+        }
+        String priorityLogPath = System.getProperty(PRIORITY_METRIC_LOG_PATH);
+        if (priorityLogPath != null) {
+            logPath = priorityLogPath;
+        } else {
+            logPath = DEFAULT_METRIC_LOG_PATH;
+        }
+    }
+
+    public static void setEnclaveMetricTraceSwitch(boolean flag) {
+        enableEnclaveMetricTrace = flag;
+    }
+
+    public static boolean isEnableEnclaveMetricTrace() {
+        return enableEnclaveMetricTrace;
+    }
+
+    abstract EnclaveInfo getEnclaveInfo();
+
+    abstract String getMetricKeyName();
+
+    abstract long getCostInnerEnclave();
+
+    void metricTracing(EnclaveInfo enclaveInfo, String name, long costTotal, 
long costEnclave) throws IOException {
+        logFile.write(String.format("%s  %s  %s  %s  %s\r\n",
+                enclaveInfo.getEnclaveID(),
+                enclaveInfo.getEnclaveType(),
+                name,
+                formatter.format(TimeUnit.NANOSECONDS.toMicros(costTotal)),
+                formatter.format(TimeUnit.NANOSECONDS.toMicros(costEnclave))));
+        logFile.flush();
+    }
+
+    @Override
+    public void close() throws MetricTraceLogWriteException {
+        try {
+            if (isEnableEnclaveMetricTrace()) {
+                if (logFile == null) {
+                    logFile = new BufferedWriter(new FileWriter(this.logPath));
+                }
+                metricTracing(getEnclaveInfo(), getMetricKeyName(), 
System.nanoTime() - start, getCostInnerEnclave());
+            }
+        } catch (IOException e) {
+            throw new MetricTraceLogWriteException(e);
+        }
+    }
+}
diff --git 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MetricTraceContext.java
 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MetricTraceContext.java
new file mode 100644
index 0000000..0084e4e
--- /dev/null
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MetricTraceContext.java
@@ -0,0 +1,62 @@
+package com.alibaba.confidentialcomputing.host;
+
+final class MetricTraceContext extends MetricTrace {
+    private EnclaveInfo info;
+    private long costInnerEnclave = 0x0;
+    private String pattern;
+
+    MetricTraceContext(EnclaveInfo info, LogPrefix prefix) {
+        this.info = info;
+        pattern = prefix.toString();
+    }
+
+    MetricTraceContext(EnclaveInfo info, LogPrefix prefix, String service) {
+        this.info = info;
+        pattern = new 
StringBuilder().append(prefix.toString()).append(":").append(service).toString();
+    }
+
+    MetricTraceContext(LogPrefix prefix) {
+        pattern = prefix.toString();
+    }
+
+    enum LogPrefix {
+        METRIC_LOG_ENCLAVE_CREATING_PATTERN("enclave_creating_cost(us)"),
+        METRIC_LOG_ENCLAVE_DESTROYING_PATTERN("enclave_destroying_cost(us)"),
+        
METRIC_LOG_ENCLAVE_SERVICE_LOADING_PATTERN("enclave_service_loading(us)"),
+        
METRIC_LOG_ENCLAVE_SERVICE_UNLOADING_PATTERN("enclave_service_unloading(us)"),
+        
METRIC_LOG_ENCLAVE_SERVICE_INVOKING_PATTERN("enclave_service_invoking(us)");
+        private final String prefix;
+
+        LogPrefix(String prefix) {
+            this.prefix = prefix;
+        }
+
+        @Override
+        public String toString() {
+            return this.prefix;
+        }
+    }
+
+    void setCostInnerEnclave(long cost) {
+        costInnerEnclave = cost;
+    }
+
+    void setEnclaveInfo(EnclaveInfo info) {
+        this.info = info;
+    }
+
+    @Override
+    EnclaveInfo getEnclaveInfo() {
+        return this.info;
+    }
+
+    @Override
+    String getMetricKeyName() {
+        return pattern;
+    }
+
+    @Override
+    long getCostInnerEnclave() {
+        return this.costInnerEnclave;
+    }
+}
diff --git 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockEnclaveInfo.java
 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockEnclaveInfo.java
index 8e790f4..ef8a510 100644
--- 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockEnclaveInfo.java
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockEnclaveInfo.java
@@ -7,6 +7,7 @@ class MockEnclaveInfo implements EnclaveInfo {
     private boolean isEnclaveDebuggable;
     private long enclaveEPCMemorySizeBytes; // Bytes.
     private int enclaveMaxThreadsNumber;
+    private int enclaveID;
 
     @ConstructorParameters({"enclaveType", "isEnclaveDebuggable", 
"enclaveEPCMemorySizeBytes", "enclaveMaxThreadsNumber"})
     MockEnclaveInfo(EnclaveType enclaveType, boolean isEnclaveDebuggable, long 
enclaveEPCMemorySizeBytes, int enclaveMaxThreadsNumber) {
@@ -14,6 +15,7 @@ class MockEnclaveInfo implements EnclaveInfo {
         this.isEnclaveDebuggable = isEnclaveDebuggable;
         this.enclaveEPCMemorySizeBytes = enclaveEPCMemorySizeBytes;
         this.enclaveMaxThreadsNumber = enclaveMaxThreadsNumber;
+        this.enclaveID = this.hashCode();
     }
 
     @Override
@@ -21,6 +23,11 @@ class MockEnclaveInfo implements EnclaveInfo {
         return this.enclaveType;
     }
 
+    @Override
+    public int getEnclaveID() {
+        return this.enclaveID;
+    }
+
     @Override
     public boolean isEnclaveDebuggable() {
         return this.isEnclaveDebuggable;
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 7ba9da0..1f5fc14 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
@@ -4,6 +4,8 @@ import 
com.alibaba.confidentialcomputing.common.EnclaveInvocationContext;
 import com.alibaba.confidentialcomputing.common.ServiceHandler;
 import com.alibaba.confidentialcomputing.host.exception.*;
 
+import java.io.IOException;
+
 /**
  * MockInJvmEnclave is a mock jvm enclave. Both host and enclave codes run
  * in one jvm. It was used for test and debug.
@@ -11,7 +13,7 @@ import com.alibaba.confidentialcomputing.host.exception.*;
 class MockInJvmEnclave extends AbstractEnclave {
     private final MockEnclaveInfo enclaveInfo;
 
-    MockInJvmEnclave() {
+    MockInJvmEnclave() throws IOException {
         // Set EnclaveContext for this enclave instance.
         super(EnclaveType.MOCK_IN_JVM, new BaseEnclaveServicesRecycler());
         enclaveInfo = new MockEnclaveInfo(EnclaveType.MOCK_IN_JVM, true, -1, 
-1);
@@ -48,6 +50,12 @@ class MockInJvmEnclave extends AbstractEnclave {
 
     @Override
     public void destroy() throws EnclaveDestroyingException {
-        EnclaveInfoManager.getEnclaveInfoManagerInstance().removeEnclave(this);
+        try (MetricTraceContext trace = new MetricTraceContext(
+                this.getEnclaveInfo(),
+                
MetricTraceContext.LogPrefix.METRIC_LOG_ENCLAVE_DESTROYING_PATTERN)) {
+            
EnclaveInfoManager.getEnclaveInfoManagerInstance().removeEnclave(this);
+        } catch (MetricTraceLogWriteException e) {
+            throw new EnclaveDestroyingException(e);
+        }
     }
 }
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 508b741..4dcf169 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
@@ -31,7 +31,6 @@ class MockInSvmEnclave extends AbstractEnclave {
     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) {
@@ -113,12 +112,18 @@ class MockInSvmEnclave extends AbstractEnclave {
     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.
-            nativeSvmDetachIsolate(enclaveSvmSdkHandle, isolateThreadHandle);
-            nativeDestroyEnclave(enclaveSvmSdkHandle);
-            
EnclaveInfoManager.getEnclaveInfoManagerInstance().removeEnclave(this);
+            try (MetricTraceContext trace = new MetricTraceContext(
+                    this.getEnclaveInfo(),
+                    
MetricTraceContext.LogPrefix.METRIC_LOG_ENCLAVE_DESTROYING_PATTERN)) {
+                // interrupt enclave services' recycler firstly.
+                
this.getEnclaveContext().getEnclaveServicesRecycler().interruptServiceRecycler();
+                // destroy svm isolate.
+                nativeSvmDetachIsolate(enclaveSvmSdkHandle, 
isolateThreadHandle);
+                nativeDestroyEnclave(enclaveSvmSdkHandle);
+                
EnclaveInfoManager.getEnclaveInfoManagerInstance().removeEnclave(this);
+            } catch (MetricTraceLogWriteException e) {
+                throw new EnclaveDestroyingException(e);
+            }
         }
     }
 
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 8666dcb..98a439d 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
@@ -1,9 +1,9 @@
 package com.alibaba.confidentialcomputing.host;
 
 import com.alibaba.confidentialcomputing.common.EnclaveInvocationContext;
+import com.alibaba.confidentialcomputing.common.EnclaveInvocationResult;
 import com.alibaba.confidentialcomputing.common.ServiceHandler;
 import 
com.alibaba.confidentialcomputing.common.exception.ConfidentialComputingException;
-import 
com.alibaba.confidentialcomputing.host.exception.EnclaveMethodInvokingException;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.InvocationHandler;
@@ -45,13 +45,14 @@ class ProxyEnclaveInvocationHandler implements 
InvocationHandler, Runnable {
         }
 
         // Handle service method invocation exception.
-        Object result;
-        try {
-            result = enclave.InvokeEnclaveMethod(methodInvokeMetaWrapper);
-        } catch (EnclaveMethodInvokingException e) {
-            // Get cause exception if it has one.
-            Throwable causeException = e.getCause();
-            if (causeException instanceof ConfidentialComputingException) {
+        try (MetricTraceContext trace = new MetricTraceContext(
+                enclave.getEnclaveInfo(),
+                
MetricTraceContext.LogPrefix.METRIC_LOG_ENCLAVE_SERVICE_INVOKING_PATTERN,
+                method.getName())) {
+            EnclaveInvocationResult result = 
enclave.InvokeEnclaveMethod(methodInvokeMetaWrapper);
+            trace.setCostInnerEnclave(result.getCost());
+            Throwable causeException = result.getException();
+            if (causeException != null && causeException instanceof 
ConfidentialComputingException) {
                 Throwable enclaveCauseException = causeException.getCause();
                 Class<?>[] exceptionTypes = method.getExceptionTypes();
                 if (enclaveCauseException instanceof 
InvocationTargetException) {
@@ -70,9 +71,8 @@ class ProxyEnclaveInvocationHandler implements 
InvocationHandler, Runnable {
                     }
                 }
             }
-            throw e;
+            return result.getResult();
         }
-        return result;
     }
 
     AbstractEnclave getEnclave() {
diff --git 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ProxyMockJvmInvocationHandler.java
 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ProxyMockJvmInvocationHandler.java
new file mode 100644
index 0000000..edfe877
--- /dev/null
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ProxyMockJvmInvocationHandler.java
@@ -0,0 +1,48 @@
+package com.alibaba.confidentialcomputing.host;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class ProxyMockJvmInvocationHandler<T> implements InvocationHandler, 
Runnable {
+    private final AbstractEnclave enclave;
+    private final T proxyService;
+
+    ProxyMockJvmInvocationHandler(AbstractEnclave enclave, T proxyService) {
+        this.enclave = enclave;
+        this.proxyService = proxyService;
+    }
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws 
Throwable {
+        Object result;
+        try (MetricTraceContext trace = new MetricTraceContext(
+                enclave.getEnclaveInfo(),
+                
MetricTraceContext.LogPrefix.METRIC_LOG_ENCLAVE_SERVICE_INVOKING_PATTERN,
+                method.getName())) {
+            result = method.invoke(proxyService, args);
+        } catch (InvocationTargetException e) {
+            // 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.
+            Class<?>[] exceptionTypes = method.getExceptionTypes();
+            Throwable rootCause = e.getCause();
+            for (Class<?> exception : exceptionTypes) {
+                if (exception == rootCause.getClass()) {
+                    throw rootCause;
+                }
+            }
+            throw e;
+        }
+        return result;
+    }
+
+    @Override
+    public void run() {
+        
enclave.getEnclaveContext().getEnclaveServicesRecycler().enqueueProxyHandler(this);
+    }
+}
diff --git 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXEnclaveInfo.java
 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXEnclaveInfo.java
index 8f61b73..1a1022d 100644
--- 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXEnclaveInfo.java
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXEnclaveInfo.java
@@ -7,6 +7,7 @@ class SGXEnclaveInfo implements EnclaveInfo {
     private boolean isEnclaveDebuggable;
     private long enclaveEPCMemorySizeBytes; // Bytes.
     private int enclaveMaxThreadsNumber;
+    private int enclaveID;
 
     @ConstructorParameters({"enclaveType", "isEnclaveDebuggable", 
"enclaveEPCMemorySizeBytes", "enclaveMaxThreadsNumber"})
     SGXEnclaveInfo(EnclaveType enclaveType, boolean isEnclaveDebuggable, long 
enclaveEPCMemorySizeBytes, int enclaveMaxThreadsNumber) {
@@ -14,6 +15,7 @@ class SGXEnclaveInfo implements EnclaveInfo {
         this.isEnclaveDebuggable = isEnclaveDebuggable;
         this.enclaveEPCMemorySizeBytes = enclaveEPCMemorySizeBytes;
         this.enclaveMaxThreadsNumber = enclaveMaxThreadsNumber;
+        this.enclaveID = this.hashCode();
     }
 
     @Override
@@ -21,6 +23,11 @@ class SGXEnclaveInfo implements EnclaveInfo {
         return this.enclaveType;
     }
 
+    @Override
+    public int getEnclaveID() {
+        return this.enclaveID;
+    }
+
     @Override
     public boolean isEnclaveDebuggable() {
         return this.isEnclaveDebuggable;
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 5bf0f1d..7179662 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
@@ -27,7 +27,6 @@ class TeeSdkEnclave extends AbstractEnclave {
     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) {
@@ -135,13 +134,19 @@ class TeeSdkEnclave extends AbstractEnclave {
     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.
-            nativeSvmDetachIsolate(enclaveHandle, isolateThreadHandle);
-            // destroy the enclave.
-            nativeDestroyEnclave(enclaveHandle);
-            
EnclaveInfoManager.getEnclaveInfoManagerInstance().removeEnclave(this);
+            try (MetricTraceContext trace = new MetricTraceContext(
+                    this.getEnclaveInfo(),
+                    
MetricTraceContext.LogPrefix.METRIC_LOG_ENCLAVE_DESTROYING_PATTERN)) {
+                // interrupt enclave services' recycler firstly.
+                
this.getEnclaveContext().getEnclaveServicesRecycler().interruptServiceRecycler();
+                // destroy svm isolate.
+                nativeSvmDetachIsolate(enclaveHandle, isolateThreadHandle);
+                // destroy the enclave.
+                nativeDestroyEnclave(enclaveHandle);
+                
EnclaveInfoManager.getEnclaveInfoManagerInstance().removeEnclave(this);
+            } catch (MetricTraceLogWriteException e) {
+                throw new EnclaveDestroyingException(e);
+            }
         }
     }
 
diff --git 
a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/MetricTraceLogWriteException.java
 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/MetricTraceLogWriteException.java
new file mode 100644
index 0000000..f244cb6
--- /dev/null
+++ 
b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/MetricTraceLogWriteException.java
@@ -0,0 +1,30 @@
+package com.alibaba.confidentialcomputing.host.exception;
+
+/**
+ * MetricTraceLogWriteException {@link MetricTraceLogWriteException} is thrown 
when an enclave metric trace
+ * write into log file.
+ * Programmers need to handle MetricTraceLogWriteException seriously.
+ */
+public class MetricTraceLogWriteException extends EnclaveCreatingException {
+    /**
+     * @param info exception information.
+     */
+    public MetricTraceLogWriteException(String info) {
+        
super(EnclaveNativeInvokingException.ENCLAVE_REMOTE_ATTESTATION_ERROR.buildExceptionMessage(info));
+    }
+
+    /**
+     * @param e exception.
+     */
+    public MetricTraceLogWriteException(Throwable e) {
+        
super(EnclaveNativeInvokingException.ENCLAVE_REMOTE_ATTESTATION_ERROR.toString(),
 e);
+    }
+
+    /**
+     * @param info exception message.
+     * @param e    exception.
+     */
+    public MetricTraceLogWriteException(String info, Throwable e) {
+        
super(EnclaveNativeInvokingException.ENCLAVE_REMOTE_ATTESTATION_ERROR.buildExceptionMessage(info),
 e);
+    }
+}
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 e4e509b..997f3e1 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
@@ -3,6 +3,7 @@ package com.alibaba.confidentialcomputing.host;
 import 
com.alibaba.confidentialcomputing.host.exception.RemoteAttestationException;
 import org.junit.jupiter.api.Test;
 
+import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
@@ -10,7 +11,7 @@ import static org.junit.jupiter.api.Assertions.*;
 
 class TestRemoteAttestation {
     @Test
-    void testRemoteAttestation() {
+    void testRemoteAttestation() throws IOException {
         Enclave mockInJvmEnclave = new MockInJvmEnclave();
         assertThrows(RemoteAttestationException.class, () -> 
RemoteAttestation.generateAttestationReport(mockInJvmEnclave, null));
         assertThrows(RemoteAttestationException.class, () -> 
RemoteAttestation.verifyAttestationReport(new 
AttestationReport(EnclaveType.MOCK_IN_JVM, null)));
diff --git a/sdk/native/script/build_app/Makefile 
b/sdk/native/script/build_app/Makefile
index ec3d6c0..9a6ce58 100644
--- a/sdk/native/script/build_app/Makefile
+++ b/sdk/native/script/build_app/Makefile
@@ -1,6 +1,8 @@
 include /opt/javaenclave/config/config.mk
 include /opt/javaenclave/config/platform/tee_sdk_svm/jni/config.mk
 
+LIB_SUNEC=sunec
+
 .PHONY: all build clean
 
 all:
@@ -17,11 +19,18 @@ ifeq ($(TEE_SDK), TRUE)
        cp ${JAVA_HOME}/lib/svm/builder/clibraries/linux-amd64/libjvm.a        
${ENCLAVE_BASE_DIR}/target/enclave_workspace
        cp ${JAVA_HOME}/lib/svm/builder/clibraries/linux-amd64/liblibchelper.a 
${ENCLAVE_BASE_DIR}/target/enclave_workspace
 
+       # copy libenc_sunec.a from svm-output to enclave_workspace if it exist.
+       cp ${ENCLAVE_BASE_DIR}/target/svm-output/libenc_sunec.a 
${ENCLAVE_BASE_DIR}/target/enclave_workspace 2>/dev/null || :
+
+    ifneq ($(wildcard 
${ENCLAVE_BASE_DIR}/target/enclave_workspace/libenc_sunec.a),)
+               LIB_SUNEC=enc_sunec
+    endif
+
        $(CC) -o ${ENCLAVE_BASE_DIR}/target/svm-output/lib_tee_sdk_svm_load \
        /opt/javaenclave/bin/platform/tee_sdk_svm/*.o 
${ENCLAVE_BASE_DIR}/target/svm-output/lib_tee_sdk_svm_load.o \
        -L${JAVA_HOME}/lib/static/linux-amd64/glibc    \
        -L${ENCLAVE_BASE_DIR}/target/enclave_workspace \
-       -fpie -ljava -lzip -lnio -lnet -ljvm -lfdlibm -llibchelper \
+       -fpie -ljava -lzip -lnio -lnet -l$(LIB_SUNEC) -ljvm -lfdlibm 
-llibchelper \
        $(TS_ENCLAVE_LDFLAGS) 
-Wl,--version-script=/opt/javaenclave/config/platform/tee_sdk_svm/edl/tee_sdk_enclave.lds
 
     ifeq ($(ENCLAVE_PRIVATE_PEM_PATH), )
diff --git 
a/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/MetricTraceService.java
 
b/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/MetricTraceService.java
new file mode 100644
index 0000000..f2e81b6
--- /dev/null
+++ 
b/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/MetricTraceService.java
@@ -0,0 +1,8 @@
+package com.alibaba.confidentialcomputing.test.common;
+
+import com.alibaba.confidentialcomputing.common.annotations.EnclaveService;
+
+@EnclaveService
+public interface MetricTraceService {
+    String invertCharacter(String str);
+}
diff --git 
a/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/SM2Service.java
 
b/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/SM2Service.java
new file mode 100644
index 0000000..9233099
--- /dev/null
+++ 
b/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/SM2Service.java
@@ -0,0 +1,8 @@
+package com.alibaba.confidentialcomputing.test.common;
+
+import com.alibaba.confidentialcomputing.common.annotations.EnclaveService;
+
+@EnclaveService
+public interface SM2Service {
+    String encryptAndDecryptWithPlaintext(String plaintext) throws Exception;
+}
diff --git 
a/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/SM3Service.java
 
b/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/SM3Service.java
new file mode 100644
index 0000000..5e64d3a
--- /dev/null
+++ 
b/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/SM3Service.java
@@ -0,0 +1,8 @@
+package com.alibaba.confidentialcomputing.test.common;
+
+import com.alibaba.confidentialcomputing.common.annotations.EnclaveService;
+
+@EnclaveService
+public interface SM3Service {
+    byte[] sm3Service(String plainText) throws Exception;
+}
diff --git 
a/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/SM4Service.java
 
b/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/SM4Service.java
new file mode 100644
index 0000000..bec5bb8
--- /dev/null
+++ 
b/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/SM4Service.java
@@ -0,0 +1,8 @@
+package com.alibaba.confidentialcomputing.test.common;
+
+import com.alibaba.confidentialcomputing.common.annotations.EnclaveService;
+
+@EnclaveService
+public interface SM4Service {
+    String sm4Service(String plaintext) throws Exception;
+}
diff --git a/test/enclave/pom.xml b/test/enclave/pom.xml
index 5bc5380..278d1e9 100644
--- a/test/enclave/pom.xml
+++ b/test/enclave/pom.xml
@@ -107,6 +107,23 @@
     </profiles>
     <build>
         <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.8.1</version>
+                <configuration>
+                    <source>11</source>
+                    <target>11</target>
+                    <compilerArgs>
+                        <arg>--add-modules</arg>
+                        <arg>jdk.internal.vm.compiler,jdk.crypto.ec</arg>
+                        <arg>--add-exports</arg>
+                        <arg>jdk.crypto.ec/sun.security.ec=ALL-UNNAMED</arg>
+                        <arg>--add-exports</arg>
+                        
<arg>jdk.internal.vm.compiler/org.graalvm.compiler.options=ALL-UNNAMED</arg>
+                    </compilerArgs>
+                </configuration>
+            </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-source-plugin</artifactId>
@@ -160,6 +177,14 @@
             <scope>compile</scope>
             <optional>true</optional>
         </dependency>
+        <dependency>
+            <groupId>com.alibaba.confidentialcomputing</groupId>
+            <artifactId>bouncycastle-native</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+        </dependency>
         <dependency>
             <groupId>com.google.auto.service</groupId>
             <artifactId>auto-service-annotations</artifactId>
diff --git 
a/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/MetricTraceServiceImpl.java
 
b/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/MetricTraceServiceImpl.java
new file mode 100644
index 0000000..b96b569
--- /dev/null
+++ 
b/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/MetricTraceServiceImpl.java
@@ -0,0 +1,17 @@
+package com.alibaba.confidentialcomputing.test.enclave;
+
+import com.alibaba.confidentialcomputing.test.common.MetricTraceService;
+import com.google.auto.service.AutoService;
+
+@AutoService(MetricTraceService.class)
+public class MetricTraceServiceImpl implements MetricTraceService {
+    @Override
+    public String invertCharacter(String str) {
+        byte[] content = new byte[str.length()];
+        byte[] initial = str.getBytes();
+        for (int i = 0x0; i < initial.length; i++) {
+            content[i] = initial[initial.length - i -1];
+        }
+        return new String(content);
+    }
+}
diff --git 
a/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/SM2ServiceImpl.java
 
b/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/SM2ServiceImpl.java
new file mode 100644
index 0000000..68e3366
--- /dev/null
+++ 
b/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/SM2ServiceImpl.java
@@ -0,0 +1,91 @@
+package com.alibaba.confidentialcomputing.test.enclave;
+
+import org.bouncycastle.asn1.gm.GMNamedCurves;
+import org.bouncycastle.asn1.x9.X9ECParameters;
+import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
+import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.jce.spec.ECParameterSpec;
+import org.bouncycastle.jce.spec.ECPrivateKeySpec;
+import org.bouncycastle.jce.spec.ECPublicKeySpec;
+import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.util.encoders.Hex;
+
+import javax.crypto.Cipher;
+import java.math.BigInteger;
+import java.security.*;
+import java.security.spec.ECGenParameterSpec;
+import java.util.Base64;
+
+import com.alibaba.confidentialcomputing.test.common.SM2Service;
+import com.google.auto.service.AutoService;
+
+@AutoService(SM2Service.class)
+public class SM2ServiceImpl implements SM2Service {
+    private BouncyCastleProvider provider;
+    private ECParameterSpec ecParameterSpec;
+    private KeyFactory keyFactory;
+    private String publicKey;
+    private String privateKey;
+
+    public SM2ServiceImpl() {
+        try {
+            provider = (BouncyCastleProvider) Security.getProvider("BC");
+            if (provider == null) {
+                provider = new BouncyCastleProvider();
+            }
+            X9ECParameters parameters = GMNamedCurves.getByName("sm2p256v1");
+            ecParameterSpec = new ECParameterSpec(parameters.getCurve(), 
parameters.getG(), parameters.getN(), parameters.getH());
+            keyFactory = KeyFactory.getInstance("EC", provider);
+            generateSm2KeyPair();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void generateSm2KeyPair() throws Exception {
+        final ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");
+        final KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", 
provider);
+        SecureRandom random = new SecureRandom();
+        kpg.initialize(sm2Spec, random);
+        KeyPair keyPair = kpg.generateKeyPair();
+        BCECPrivateKey privateKey = (BCECPrivateKey) keyPair.getPrivate();
+        BCECPublicKey publicKey = (BCECPublicKey) keyPair.getPublic();
+        this.publicKey = new 
String(Hex.encode(publicKey.getQ().getEncoded(true)));
+        this.privateKey = privateKey.getD().toString(16);
+    }
+
+    private String encode(String input, String pubKey) {
+        try {
+            X9ECParameters parameters = GMNamedCurves.getByName("sm2p256v1");
+            ECParameterSpec ecParameterSpec = new 
ECParameterSpec(parameters.getCurve(), parameters.getG(), parameters.getN(), 
parameters.getH());
+            ECPoint ecPoint = 
parameters.getCurve().decodePoint(Hex.decode(pubKey));
+            KeyFactory keyFactory = KeyFactory.getInstance("EC", provider);
+            BCECPublicKey key = (BCECPublicKey) keyFactory.generatePublic(new 
ECPublicKeySpec(ecPoint, ecParameterSpec));
+            Cipher cipher = Cipher.getInstance("SM2", provider);
+            cipher.init(Cipher.ENCRYPT_MODE, key);
+            return 
Base64.getEncoder().encodeToString(cipher.doFinal(input.getBytes()));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    private byte[] decoder(String input, String prvKey) {
+        try {
+            Cipher cipher = Cipher.getInstance("SM2", provider);
+            BigInteger bigInteger = new BigInteger(prvKey, 16);
+            BCECPrivateKey privateKey = (BCECPrivateKey) 
keyFactory.generatePrivate(new ECPrivateKeySpec(bigInteger, ecParameterSpec));
+            cipher.init(Cipher.DECRYPT_MODE, privateKey);
+            return cipher.doFinal(Base64.getDecoder().decode(input));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    @Override
+    public String encryptAndDecryptWithPlaintext(String plaintext) throws 
Exception {
+        return new String(decoder(encode(plaintext, publicKey), privateKey));
+    }
+}
diff --git 
a/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/SM3ServiceImpl.java
 
b/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/SM3ServiceImpl.java
new file mode 100644
index 0000000..dcb1bf8
--- /dev/null
+++ 
b/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/SM3ServiceImpl.java
@@ -0,0 +1,19 @@
+package com.alibaba.confidentialcomputing.test.enclave;
+
+import com.alibaba.confidentialcomputing.test.common.SM3Service;
+import com.google.auto.service.AutoService;
+import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.digests.SM3Digest;
+
+@AutoService(SM3Service.class)
+public class SM3ServiceImpl implements SM3Service {
+    @Override
+    public byte[] sm3Service(String plainText) throws Exception {
+        byte[] messages = plainText.getBytes();
+        Digest md = new SM3Digest();
+        md.update(messages, 0, messages.length);
+        byte[] digest = new byte[md.getDigestSize()];
+        md.doFinal(digest, 0);
+        return digest;
+    }
+}
diff --git 
a/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/SM4ServiceImpl.java
 
b/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/SM4ServiceImpl.java
new file mode 100644
index 0000000..bab25b2
--- /dev/null
+++ 
b/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/SM4ServiceImpl.java
@@ -0,0 +1,57 @@
+package com.alibaba.confidentialcomputing.test.enclave;
+
+import com.alibaba.confidentialcomputing.test.common.SM4Service;
+import com.google.auto.service.AutoService;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
+import java.security.Provider;
+import java.security.SecureRandom;
+import java.security.Security;
+
+@AutoService(SM4Service.class)
+public class SM4ServiceImpl implements SM4Service {
+    private static final String ALGORITHM_NAME = "SM4";
+    private static final String ALGORITHM_ECB_PKCS5PADDING = 
"SM4/ECB/PKCS5Padding";
+    private static final int DEFAULT_KEY_SIZE = 128;
+
+    static {
+        Provider provider = Security.getProvider("BC");
+        if (provider == null) {
+            provider = new BouncyCastleProvider();
+        }
+        Security.addProvider(provider);
+    }
+
+    private byte[] generateKey() throws Exception {
+        KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, 
BouncyCastleProvider.PROVIDER_NAME);
+        kg.init(DEFAULT_KEY_SIZE, new SecureRandom());
+        return kg.generateKey().getEncoded();
+    }
+
+    private byte[] sm4EncryptAndDecrypt(byte[] data, byte[] key, String 
sm4mode, byte[] iv, int mode) throws Exception {
+        IvParameterSpec ivParameterSpec = null;
+        if (null != iv) {
+            ivParameterSpec = new IvParameterSpec(iv);
+        }
+        SecretKeySpec sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);
+        Cipher cipher = Cipher.getInstance(sm4mode, 
BouncyCastleProvider.PROVIDER_NAME);
+        if (null == ivParameterSpec) {
+            cipher.init(mode, sm4Key);
+        } else {
+            cipher.init(mode, sm4Key, ivParameterSpec);
+        }
+        return cipher.doFinal(data);
+    }
+
+    @Override
+    public String sm4Service(String plaintext) throws Exception {
+        byte[] key = generateKey();
+        byte[] encryptResult = 
sm4EncryptAndDecrypt(plaintext.getBytes(StandardCharsets.UTF_8), key, 
ALGORITHM_ECB_PKCS5PADDING, null, Cipher.ENCRYPT_MODE);
+        return new String(sm4EncryptAndDecrypt(encryptResult, key, 
ALGORITHM_ECB_PKCS5PADDING, null, Cipher.DECRYPT_MODE), StandardCharsets.UTF_8);
+    }
+}
diff --git 
a/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestEnclaveMetricTrace.java
 
b/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestEnclaveMetricTrace.java
new file mode 100644
index 0000000..3bba0f3
--- /dev/null
+++ 
b/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestEnclaveMetricTrace.java
@@ -0,0 +1,67 @@
+package com.alibaba.confidentialcomputing.test.host;
+
+import com.alibaba.confidentialcomputing.host.Enclave;
+import com.alibaba.confidentialcomputing.host.EnclaveFactory;
+import com.alibaba.confidentialcomputing.host.EnclaveType;
+import com.alibaba.confidentialcomputing.host.MetricTrace;
+import com.alibaba.confidentialcomputing.test.common.MetricTraceService;
+import org.junit.jupiter.api.Test;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.util.Iterator;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class TestEnclaveMetricTrace {
+    private String invertCharacter(String str) {
+        byte[] content = new byte[str.length()];
+        byte[] initial = str.getBytes();
+        for (int i = 0x0; i < initial.length; i++) {
+            content[i] = initial[initial.length - i - 1];
+        }
+        return new String(content);
+    }
+
+    @Test
+    public void testEnclaveMetricTrace() throws Exception {
+        MetricTrace.setEnclaveMetricTraceSwitch(true);
+        String plaintext = "ABC_DEF_GHI_JKL_MNO_PQR_STU_VWX_YZ";
+        EnclaveType[] types = new EnclaveType[] {
+                EnclaveType.MOCK_IN_JVM,
+                EnclaveType.MOCK_IN_SVM,
+                EnclaveType.TEE_SDK,
+                EnclaveType.EMBEDDED_LIB_OS};
+        for (EnclaveType type : types) {
+            Enclave enclave = EnclaveFactory.create(type);
+            assertNotNull(enclave);
+            Iterator<MetricTraceService> userServices = 
enclave.load(MetricTraceService.class);
+            assertNotNull(userServices);
+            assertTrue(userServices.hasNext());
+            MetricTraceService service = userServices.next();
+            String result = service.invertCharacter(plaintext);
+            assertEquals(result, invertCharacter(plaintext));
+            enclave.destroy();
+        }
+        MetricTrace.setEnclaveMetricTraceSwitch(false);
+
+        Field flog = MetricTrace.class.getDeclaredField("logPath");
+        flog.setAccessible(true);
+        String logPath = (String) flog.get(null);
+        assertNotNull(logPath);
+        File file = new File(logPath);
+        assertTrue(file.exists());
+        InputStream in = new FileInputStream(logPath);
+        byte[] buffer = new byte[in.available()];
+        in.read(buffer);
+        String str = new String(buffer);
+        assertTrue(str.contains("enclave_creating_cost"));
+        assertTrue(str.contains("enclave_destroying_cost"));
+        assertTrue(str.contains("enclave_service_loading"));
+        assertTrue(str.contains("TEE_SDK"));
+        assertTrue(str.contains("EMBEDDED_LIB_OS"));
+        assertTrue(file.delete());
+    }
+}
diff --git 
a/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestSMEnclave.java
 
b/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestSMEnclave.java
new file mode 100644
index 0000000..aa12f33
--- /dev/null
+++ 
b/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestSMEnclave.java
@@ -0,0 +1,91 @@
+package com.alibaba.confidentialcomputing.test.host;
+
+import com.alibaba.confidentialcomputing.host.Enclave;
+import com.alibaba.confidentialcomputing.host.EnclaveFactory;
+import com.alibaba.confidentialcomputing.host.EnclaveType;
+import com.alibaba.confidentialcomputing.test.common.SM2Service;
+import com.alibaba.confidentialcomputing.test.common.SM3Service;
+import com.alibaba.confidentialcomputing.test.common.SM4Service;
+import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.digests.SM3Digest;
+import org.junit.jupiter.api.Test;
+
+import java.util.Iterator;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class TestSMEnclave {
+    private byte[] sm3Digest(String plaintext) {
+        byte[] messages = plaintext.getBytes();
+        Digest md = new SM3Digest();
+        md.update(messages, 0, messages.length);
+        byte[] digest = new byte[md.getDigestSize()];
+        md.doFinal(digest, 0);
+        return digest;
+    }
+
+    @Test
+    public void testSM2Enclave() throws Exception {
+        String plaintext = "Hello World!!!";
+        EnclaveType[] types = new EnclaveType[]{
+                EnclaveType.MOCK_IN_JVM,
+                EnclaveType.MOCK_IN_SVM,
+                EnclaveType.TEE_SDK,
+                EnclaveType.EMBEDDED_LIB_OS};
+
+        for (EnclaveType type : types) {
+            Enclave enclave = EnclaveFactory.create(type);
+            assertNotNull(enclave);
+            Iterator<SM2Service> userServices = enclave.load(SM2Service.class);
+            assertNotNull(userServices);
+            assertTrue(userServices.hasNext());
+            SM2Service service = userServices.next();
+            String result = service.encryptAndDecryptWithPlaintext(plaintext);
+            assertEquals(plaintext, result);
+            enclave.destroy();
+        }
+    }
+
+    @Test
+    public void testSM3Enclave() throws Exception {
+        String plaintext = "Hello World!!!";
+        EnclaveType[] types = new EnclaveType[]{
+                EnclaveType.MOCK_IN_JVM,
+                EnclaveType.MOCK_IN_SVM,
+                EnclaveType.TEE_SDK,
+                EnclaveType.EMBEDDED_LIB_OS};
+
+        for (EnclaveType type : types) {
+            Enclave enclave = EnclaveFactory.create(type);
+            assertNotNull(enclave);
+            Iterator<SM3Service> userServices = enclave.load(SM3Service.class);
+            assertNotNull(userServices);
+            assertTrue(userServices.hasNext());
+            SM3Service service = userServices.next();
+            byte[] result = service.sm3Service(plaintext);
+            assertArrayEquals(sm3Digest(plaintext), result);
+            enclave.destroy();
+        }
+    }
+
+    @Test
+    public void testSM4Enclave() throws Exception {
+        String plaintext = "Hello World!!!";
+        EnclaveType[] types = new EnclaveType[]{
+                EnclaveType.MOCK_IN_JVM,
+                EnclaveType.MOCK_IN_SVM,
+                EnclaveType.TEE_SDK,
+                EnclaveType.EMBEDDED_LIB_OS};
+
+        for (EnclaveType type : types) {
+            Enclave enclave = EnclaveFactory.create(type);
+            assertNotNull(enclave);
+            Iterator<SM4Service> userServices = enclave.load(SM4Service.class);
+            assertNotNull(userServices);
+            assertTrue(userServices.hasNext());
+            SM4Service service = userServices.next();
+            assertEquals(service.sm4Service(plaintext), plaintext);
+            enclave.destroy();
+        }
+    }
+}
diff --git a/test/pom.xml b/test/pom.xml
index 97e1d9b..a5e79dd 100644
--- a/test/pom.xml
+++ b/test/pom.xml
@@ -12,6 +12,7 @@
         <maven.compiler.source>11</maven.compiler.source>
         <maven.compiler.target>11</maven.compiler.target>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <graal.version>22.2.0</graal.version>
         
<com.alibaba.enclave.platform>MOCK_IN_SVM:TEE_SDK:EMBEDDED_LIB_OS</com.alibaba.enclave.platform>
     </properties>
     <dependencyManagement>
@@ -46,6 +47,16 @@
                 <artifactId>host</artifactId>
                 <version>0.1.0</version>
             </dependency>
+            <dependency>
+                <groupId>com.alibaba.confidentialcomputing</groupId>
+                <artifactId>bouncycastle-native</artifactId>
+                <version>1.0-SNAPSHOT</version>
+            </dependency>
+            <dependency>
+                <groupId>org.bouncycastle</groupId>
+                <artifactId>bcprov-jdk15on</artifactId>
+                <version>1.66</version>
+            </dependency>
             <dependency>
                 <groupId>org.junit.jupiter</groupId>
                 <artifactId>junit-jupiter-api</artifactId>
@@ -83,4 +94,4 @@
         <module>enclave</module>
         <module>host</module>
     </modules>
-</project>
+</project>
\ No newline at end of file
diff --git a/tools/cicd/Dockerfile b/tools/cicd/Dockerfile
index e010d98..cdac972 100644
--- a/tools/cicd/Dockerfile
+++ b/tools/cicd/Dockerfile
@@ -10,7 +10,7 @@ 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/"]
+ADD ["sgx_linux_x64_sdk_2.17.100.1.bin", "/root/tools/"]
 ENV GRAALVM_HOME "/root/tools/graalvm-ce-java11-22.2.0"
 ENV JAVA_HOME "/root/tools/graalvm-ce-java11-22.2.0"
 ENV PATH="/opt/occlum/build/bin:/usr/local/occlum/bin:$PATH"
@@ -39,7 +39,7 @@ RUN apt-get update && apt-get install -y gdb gnupg wget 
aptitude libfuse-dev lib
     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=/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
+    cd /root/tools && chmod 777 sgx_linux_x64_sdk_2.17.100.1.bin && echo -e 
'no\n/opt/teesdk\n' | ./sgx_linux_x64_sdk_2.17.100.1.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
diff --git a/tools/cicd/make.sh b/tools/cicd/make.sh
index 971b8b7..c05d6f3 100755
--- a/tools/cicd/make.sh
+++ b/tools/cicd/make.sh
@@ -3,7 +3,7 @@
 MODE=$1
 
 BUILD_IMAGE=javaenclave_build
-BUILD_TAG=v0.1.11
+BUILD_TAG=v0.1.12
 
 SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
 
@@ -17,13 +17,13 @@ if [[ "$(docker images -q ${BUILD_IMAGE}:${BUILD_TAG} 2> 
/dev/null)" == "" ]]; t
   wget 
http://graal.oss-cn-beijing.aliyuncs.com/graal-enclave/JDK11-22.2.0/graalvm-ce-java11-22.2.0.tar
   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/tee_java/dependency/sgx_linux_x64_sdk_2.17.100.1.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-ce-java11-22.2.0.tar
   rm -f settings.xml
   rm -f zlib-1.2.11.tar.gz
-  rm -f sgx_linux_x64_sdk_2.17.100.0.bin
+  rm -f sgx_linux_x64_sdk_2.17.100.1.bin
   rm -f Alibaba_Dragonwell_11.0.15.11.9_x64_alpine-linux.tar.gz
 fi
 


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

Reply via email to