Repository: deepjavalibrary/djl
Pull request #2929 (2024-01-09 18:51:52)

[pytorch] Allows to load libstdc++.so.6 form different location
## Description ##

Brief description of what this PR is about

- If this change is a backward incompatible change, why must this change be made?
- Interesting edge cases to note here



Patch:
diff --git a/api/src/main/java/ai/djl/Device.java b/api/src/main/java/ai/djl/Device.java
index b99e5a648..597d7d9be 100644
--- a/api/src/main/java/ai/djl/Device.java
+++ b/api/src/main/java/ai/djl/Device.java
@@ -15,6 +15,7 @@ package ai.djl;
 import ai.djl.engine.Engine;
 
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
@@ -162,6 +163,15 @@ public class Device {
         return Type.GPU.equals(deviceType);
     }
 
+    /**
+     * Returns the sub devices if present (such as a {@link MultiDevice}), otherwise this.
+     *
+     * @return the sub devices if present (such as a {@link MultiDevice}), otherwise this.
+     */
+    public List<Device> getDevices() {
+        return Collections.singletonList(this);
+    }
+
     /** {@inheritDoc} */
     @Override
     public String toString() {
@@ -276,11 +286,8 @@ public class Device {
             this.devices = devices;
         }
 
-        /**
-         * Returns the sub devices.
-         *
-         * @return the sub devices
-         */
+        /** {@inheritDoc} */
+        @Override
         public List<Device> getDevices() {
             return devices;
         }
diff --git a/api/src/main/java/ai/djl/engine/Engine.java b/api/src/main/java/ai/djl/engine/Engine.java
index 8a1fc8871..a799c70f6 100644
--- a/api/src/main/java/ai/djl/engine/Engine.java
+++ b/api/src/main/java/ai/djl/engine/Engine.java
@@ -59,7 +59,7 @@ public abstract class Engine {
 
     private static final Map<String, EngineProvider> ALL_ENGINES = new ConcurrentHashMap<>();
 
-    private static final String DEFAULT_ENGINE = initEngine();
+    private static String defaultEngine = initEngine();
     private static final Pattern PATTERN =
             Pattern.compile("KEY|TOKEN|PASSWORD", Pattern.CASE_INSENSITIVE);
 
@@ -69,6 +69,10 @@ public abstract class Engine {
     private Integer seed;
 
     private static synchronized String initEngine() {
+        if (Boolean.parseBoolean(Utils.getenv("DJL_ENGINE_MANUAL_INIT"))) {
+            return null;
+        }
+
         ServiceLoader<EngineProvider> loaders = ServiceLoader.load(EngineProvider.class);
         for (EngineProvider provider : loaders) {
             registerEngine(provider);
@@ -80,21 +84,21 @@ public abstract class Engine {
         }
 
         String def = System.getProperty("ai.djl.default_engine");
-        String defaultEngine = Utils.getenv("DJL_DEFAULT_ENGINE", def);
-        if (defaultEngine == null || defaultEngine.isEmpty()) {
+        String newDefaultEngine = Utils.getenv("DJL_DEFAULT_ENGINE", def);
+        if (newDefaultEngine == null || newDefaultEngine.isEmpty()) {
             int rank = Integer.MAX_VALUE;
             for (EngineProvider provider : ALL_ENGINES.values()) {
                 if (provider.getEngineRank() < rank) {
-                    defaultEngine = provider.getEngineName();
+                    newDefaultEngine = provider.getEngineName();
                     rank = provider.getEngineRank();
                 }
             }
-        } else if (!ALL_ENGINES.containsKey(defaultEngine)) {
-            throw new EngineException("Unknown default engine: " + defaultEngine);
+        } else if (!ALL_ENGINES.containsKey(newDefaultEngine)) {
+            throw new EngineException("Unknown default engine: " + newDefaultEngine);
         }
-        logger.debug("Found default engine: {}", defaultEngine);
-        Ec2Utils.callHome(defaultEngine);
-        return defaultEngine;
+        logger.debug("Found default engine: {}", newDefaultEngine);
+        Ec2Utils.callHome(newDefaultEngine);
+        return newDefaultEngine;
     }
 
     /**
@@ -124,7 +128,7 @@ public abstract class Engine {
      * @return the default Engine name
      */
     public static String getDefaultEngineName() {
-        return System.getProperty("ai.djl.default_engine", DEFAULT_ENGINE);
+        return System.getProperty("ai.djl.default_engine", defaultEngine);
     }
 
     /**
@@ -134,7 +138,7 @@ public abstract class Engine {
      * @see EngineProvider
      */
     public static Engine getInstance() {
-        if (DEFAULT_ENGINE == null) {
+        if (defaultEngine == null) {
             throw new EngineException(
                     "No deep learning engine found."
                             + System.lineSeparator()
@@ -163,7 +167,29 @@ public abstract class Engine {
      */
     public static void registerEngine(EngineProvider provider) {
         logger.debug("Registering EngineProvider: {}", provider.getEngineName());
-        ALL_ENGINES.putIfAbsent(provider.getEngineName(), provider);
+        ALL_ENGINES.put(provider.getEngineName(), provider);
+    }
+
+    /**
+     * Returns the default engine.
+     *
+     * @return the default engine
+     */
+    public static String getDefaultEngine() {
+        return defaultEngine;
+    }
+
+    /**
+     * Sets the default engine returned by {@link #getInstance()}.
+     *
+     * @param engineName the new default engine's name
+     */
+    public static void setDefaultEngine(String engineName) {
+        // Requires an engine to be loaded (without exception) before being the default
+        getEngine(engineName);
+
+        logger.debug("Setting new default engine: {}", engineName);
+        defaultEngine = engineName;
     }
 
     /**
@@ -187,7 +213,12 @@ public abstract class Engine {
         if (provider == null) {
             throw new IllegalArgumentException("Deep learning engine not found: " + engineName);
         }
-        return provider.getEngine();
+        Engine engine = provider.getEngine();
+        if (engine == null) {
+            throw new IllegalStateException(
+                    "The engine " + engineName + " was not able to initialize");
+        }
+        return engine;
     }
 
     /**
diff --git a/docs/development/troubleshooting.md b/docs/development/troubleshooting.md
index ff03d3264..1a04592dc 100644
--- a/docs/development/troubleshooting.md
+++ b/docs/development/troubleshooting.md
@@ -105,6 +105,11 @@ For more information, please refer to [DJL Cache Management](cache_management.md
 It happened when you had a wrong version with DJL and Deep Engines. 
 You can check the combination [here](dependency_management.md) and use DJL BOM to solve the issue.
 
+### 1.6 Manual initialization
+
+If you are using manual engine initialization, you must both register an engine and set it as the default.
+This can be done with `Engine.registerEngine(..)` and `Engine.setDefaultEngine(..)`.
+
 ## 2. IntelliJ throws the `No Log4j 2 configuration file found.` exception.
 The following exception may appear after running the `./gradlew clean` command:
 
diff --git a/engines/ml/lightgbm/src/main/java/ai/djl/ml/lightgbm/LgbmEngineProvider.java b/engines/ml/lightgbm/src/main/java/ai/djl/ml/lightgbm/LgbmEngineProvider.java
index f8c84c753..583cd8132 100644
--- a/engines/ml/lightgbm/src/main/java/ai/djl/ml/lightgbm/LgbmEngineProvider.java
+++ b/engines/ml/lightgbm/src/main/java/ai/djl/ml/lightgbm/LgbmEngineProvider.java
@@ -18,6 +18,9 @@ import ai.djl.engine.EngineProvider;
 /** {@code LgbmEngineProvider} is the LightGBM implementation of {@link EngineProvider}. */
 public class LgbmEngineProvider implements EngineProvider {
 
+    private volatile Engine engine; // NOPMD
+    private volatile boolean initialized; // NOPMD
+
     /** {@inheritDoc} */
     @Override
     public String getEngineName() {
@@ -33,10 +36,14 @@ public class LgbmEngineProvider implements EngineProvider {
     /** {@inheritDoc} */
     @Override
     public Engine getEngine() {
-        return InstanceHolder.INSTANCE;
-    }
-
-    private static class InstanceHolder {
-        static final Engine INSTANCE = LgbmEngine.newInstance();
+        if (!initialized) {
+            synchronized (LgbmEngineProvider.class) {
+                if (!initialized) {
+                    initialized = true;
+                    engine = LgbmEngine.newInstance();
+                }
+            }
+        }
+        return engine;
     }
 }
diff --git a/engines/ml/xgboost/src/main/java/ai/djl/ml/xgboost/XgbEngineProvider.java b/engines/ml/xgboost/src/main/java/ai/djl/ml/xgboost/XgbEngineProvider.java
index 5859f3f34..8b534d519 100644
--- a/engines/ml/xgboost/src/main/java/ai/djl/ml/xgboost/XgbEngineProvider.java
+++ b/engines/ml/xgboost/src/main/java/ai/djl/ml/xgboost/XgbEngineProvider.java
@@ -18,6 +18,9 @@ import ai.djl.engine.EngineProvider;
 /** {@code XgbEngineProvider} is the XGBoost implementation of {@link EngineProvider}. */
 public class XgbEngineProvider implements EngineProvider {
 
+    private volatile Engine engine; // NOPMD
+    private volatile boolean initialized; // NOPMD
+
     /** {@inheritDoc} */
     @Override
     public String getEngineName() {
@@ -33,10 +36,14 @@ public class XgbEngineProvider implements EngineProvider {
     /** {@inheritDoc} */
     @Override
     public Engine getEngine() {
-        return InstanceHolder.INSTANCE;
-    }
-
-    private static class InstanceHolder {
-        static final Engine INSTANCE = XgbEngine.newInstance();
+        if (!initialized) {
+            synchronized (XgbEngineProvider.class) {
+                if (!initialized) {
+                    initialized = true;
+                    engine = XgbEngine.newInstance();
+                }
+            }
+        }
+        return engine;
     }
 }
diff --git a/engines/mxnet/mxnet-engine/src/main/java/ai/djl/mxnet/engine/MxEngineProvider.java b/engines/mxnet/mxnet-engine/src/main/java/ai/djl/mxnet/engine/MxEngineProvider.java
index 5f45116f6..2a5ab9705 100644
--- a/engines/mxnet/mxnet-engine/src/main/java/ai/djl/mxnet/engine/MxEngineProvider.java
+++ b/engines/mxnet/mxnet-engine/src/main/java/ai/djl/mxnet/engine/MxEngineProvider.java
@@ -18,6 +18,9 @@ import ai.djl.engine.EngineProvider;
 /** {@code MxEngineProvider} is the MXNet implementation of {@link EngineProvider}. */
 public class MxEngineProvider implements EngineProvider {
 
+    private volatile Engine engine; // NOPMD
+    private volatile boolean initialized; // NOPMD
+
     /** {@inheritDoc} */
     @Override
     public String getEngineName() {
@@ -33,10 +36,14 @@ public class MxEngineProvider implements EngineProvider {
     /** {@inheritDoc} */
     @Override
     public Engine getEngine() {
-        return InstanceHolder.INSTANCE;
-    }
-
-    private static class InstanceHolder {
-        static final Engine INSTANCE = MxEngine.newInstance();
+        if (!initialized) {
+            synchronized (MxEngineProvider.class) {
+                if (!initialized) {
+                    initialized = true;
+                    engine = MxEngine.newInstance();
+                }
+            }
+        }
+        return engine;
     }
 }
diff --git a/engines/onnxruntime/onnxruntime-engine/src/main/java/ai/djl/onnxruntime/engine/OrtEngineProvider.java b/engines/onnxruntime/onnxruntime-engine/src/main/java/ai/djl/onnxruntime/engine/OrtEngineProvider.java
index 005c0fa25..5616eb80e 100644
--- a/engines/onnxruntime/onnxruntime-engine/src/main/java/ai/djl/onnxruntime/engine/OrtEngineProvider.java
+++ b/engines/onnxruntime/onnxruntime-engine/src/main/java/ai/djl/onnxruntime/engine/OrtEngineProvider.java
@@ -18,6 +18,9 @@ import ai.djl.engine.EngineProvider;
 /** {@code OrtEngineProvider} is the ONNX Runtime implementation of {@link EngineProvider}. */
 public class OrtEngineProvider implements EngineProvider {
 
+    private volatile Engine engine; // NOPMD
+    private volatile boolean initialized; // NOPMD
+
     /** {@inheritDoc} */
     @Override
     public String getEngineName() {
@@ -33,10 +36,14 @@ public class OrtEngineProvider implements EngineProvider {
     /** {@inheritDoc} */
     @Override
     public Engine getEngine() {
-        return InstanceHolder.INSTANCE;
-    }
-
-    private static class InstanceHolder {
-        static final Engine INSTANCE = OrtEngine.newInstance();
+        if (!initialized) {
+            synchronized (OrtEngineProvider.class) {
+                if (!initialized) {
+                    initialized = true;
+                    engine = OrtEngine.newInstance();
+                }
+            }
+        }
+        return engine;
     }
 }
diff --git a/engines/paddlepaddle/paddlepaddle-engine/src/main/java/ai/djl/paddlepaddle/engine/PpEngineProvider.java b/engines/paddlepaddle/paddlepaddle-engine/src/main/java/ai/djl/paddlepaddle/engine/PpEngineProvider.java
index 59e5cd907..e2fb86974 100644
--- a/engines/paddlepaddle/paddlepaddle-engine/src/main/java/ai/djl/paddlepaddle/engine/PpEngineProvider.java
+++ b/engines/paddlepaddle/paddlepaddle-engine/src/main/java/ai/djl/paddlepaddle/engine/PpEngineProvider.java
@@ -18,6 +18,9 @@ import ai.djl.engine.EngineProvider;
 /** {@code PpEngineProvider} is the PaddlePaddle implementation of {@link EngineProvider}. */
 public class PpEngineProvider implements EngineProvider {
 
+    private volatile Engine engine; // NOPMD
+    private volatile boolean initialized; // NOPMD
+
     /** {@inheritDoc} */
     @Override
     public String getEngineName() {
@@ -33,10 +36,14 @@ public class PpEngineProvider implements EngineProvider {
     /** {@inheritDoc} */
     @Override
     public Engine getEngine() {
-        return InstanceHolder.INSTANCE;
-    }
-
-    private static class InstanceHolder {
-        static final Engine INSTANCE = PpEngine.newInstance();
+        if (!initialized) {
+            synchronized (PpEngineProvider.class) {
+                if (!initialized) {
+                    initialized = true;
+                    engine = PpEngine.newInstance();
+                }
+            }
+        }
+        return engine;
     }
 }
diff --git a/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/engine/PtEngineProvider.java b/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/engine/PtEngineProvider.java
index 42ca3c5b8..24be3e91d 100644
--- a/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/engine/PtEngineProvider.java
+++ b/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/engine/PtEngineProvider.java
@@ -18,7 +18,8 @@ import ai.djl.engine.EngineProvider;
 /** {@code PtEngineProvider} is the PyTorch implementation of {@link EngineProvider}. */
 public class PtEngineProvider implements EngineProvider {
 
-    private static volatile Engine engine; // NOPMD
+    private volatile Engine engine; // NOPMD
+    private volatile boolean initialized; // NOPMD
 
     /** {@inheritDoc} */
     @Override
@@ -35,9 +36,10 @@ public class PtEngineProvider implements EngineProvider {
     /** {@inheritDoc} */
     @Override
     public Engine getEngine() {
-        if (engine == null) {
+        if (!initialized) {
             synchronized (PtEngineProvider.class) {
-                if (engine == null) {
+                if (!initialized) {
+                    initialized = true;
                     engine = PtEngine.newInstance();
                 }
             }
diff --git a/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/jni/LibUtils.java b/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/jni/LibUtils.java
index b28a7a9d1..03835b6ca 100644
--- a/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/jni/LibUtils.java
+++ b/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/jni/LibUtils.java
@@ -106,6 +106,17 @@ public final class LibUtils {
 
     private static void loadLibTorch(LibTorch libTorch) {
         Path libDir = libTorch.dir.toAbsolutePath();
+        if (Files.exists(libDir.resolve("libstdc++.so.6"))) {
+            String libstd = Utils.getEnvOrSystemProperty("LIBSTDCXX_LIBRARY_PATH");
+            if (libstd != null) {
+                try {
+                    logger.info("Loading libstdc++.so.6 from: {}", libstd);
+                    System.load(libstd);
+                } catch (UnsatisfiedLinkError e) {
+                    logger.warn("Failed Loading libstdc++.so.6 from: {}", libstd);
+                }
+            }
+        }
         boolean isCuda = libTorch.flavor.contains("cu");
         List<String> deferred =
                 Arrays.asList(
diff --git a/engines/tensorflow/tensorflow-engine/src/main/java/ai/djl/tensorflow/engine/TfEngineProvider.java b/engines/tensorflow/tensorflow-engine/src/main/java/ai/djl/tensorflow/engine/TfEngineProvider.java
index ad440a479..fa7813a49 100644
--- a/engines/tensorflow/tensorflow-engine/src/main/java/ai/djl/tensorflow/engine/TfEngineProvider.java
+++ b/engines/tensorflow/tensorflow-engine/src/main/java/ai/djl/tensorflow/engine/TfEngineProvider.java
@@ -18,7 +18,8 @@ import ai.djl.engine.EngineProvider;
 /** {@code TfEngineProvider} is the TensorFlow implementation of {@link EngineProvider}. */
 public class TfEngineProvider implements EngineProvider {
 
-    private static volatile Engine engine; // NOPMD
+    private volatile Engine engine; // NOPMD
+    private volatile boolean initialized; // NOPMD
 
     /** {@inheritDoc} */
     @Override
@@ -35,9 +36,10 @@ public class TfEngineProvider implements EngineProvider {
     /** {@inheritDoc} */
     @Override
     public Engine getEngine() {
-        if (engine == null) {
+        if (!initialized) {
             synchronized (TfEngineProvider.class) {
-                if (engine == null) {
+                if (!initialized) {
+                    initialized = true;
                     engine = TfEngine.newInstance();
                 }
             }
diff --git a/engines/tensorrt/src/main/java/ai/djl/tensorrt/engine/TrtEngineProvider.java b/engines/tensorrt/src/main/java/ai/djl/tensorrt/engine/TrtEngineProvider.java
index d92ed9e44..8c90859c6 100644
--- a/engines/tensorrt/src/main/java/ai/djl/tensorrt/engine/TrtEngineProvider.java
+++ b/engines/tensorrt/src/main/java/ai/djl/tensorrt/engine/TrtEngineProvider.java
@@ -18,6 +18,9 @@ import ai.djl.engine.EngineProvider;
 /** {@code TrtEngineProvider} is the TensorRT implementation of {@link EngineProvider}. */
 public class TrtEngineProvider implements EngineProvider {
 
+    private volatile Engine engine; // NOPMD
+    private volatile boolean initialized; // NOPMD
+
     /** {@inheritDoc} */
     @Override
     public String getEngineName() {
@@ -33,10 +36,14 @@ public class TrtEngineProvider implements EngineProvider {
     /** {@inheritDoc} */
     @Override
     public Engine getEngine() {
-        return InstanceHolder.INSTANCE;
-    }
-
-    private static class InstanceHolder {
-        static final Engine INSTANCE = TrtEngine.newInstance();
+        if (!initialized) {
+            synchronized (TrtEngineProvider.class) {
+                if (!initialized) {
+                    initialized = true;
+                    engine = TrtEngine.newInstance();
+                }
+            }
+        }
+        return engine;
     }
 }
diff --git a/engines/tflite/tflite-engine/src/main/java/ai/djl/tflite/engine/TfLiteEngineProvider.java b/engines/tflite/tflite-engine/src/main/java/ai/djl/tflite/engine/TfLiteEngineProvider.java
index fb61551a3..b46cad53b 100644
--- a/engines/tflite/tflite-engine/src/main/java/ai/djl/tflite/engine/TfLiteEngineProvider.java
+++ b/engines/tflite/tflite-engine/src/main/java/ai/djl/tflite/engine/TfLiteEngineProvider.java
@@ -18,6 +18,9 @@ import ai.djl.engine.EngineProvider;
 /** {@code TfLiteEngineProvider} is the TFLite implementation of {@link EngineProvider}. */
 public class TfLiteEngineProvider implements EngineProvider {
 
+    private volatile Engine engine; // NOPMD
+    private volatile boolean initialized; // NOPMD
+
     /** {@inheritDoc} */
     @Override
     public String getEngineName() {
@@ -33,10 +36,14 @@ public class TfLiteEngineProvider implements EngineProvider {
     /** {@inheritDoc} */
     @Override
     public Engine getEngine() {
-        return InstanceHolder.INSTANCE;
-    }
-
-    private static class InstanceHolder {
-        static final Engine INSTANCE = TfLiteEngine.newInstance();
+        if (!initialized) {
+            synchronized (TfLiteEngineProvider.class) {
+                if (!initialized) {
+                    initialized = true;
+                    engine = TfLiteEngine.newInstance();
+                }
+            }
+        }
+        return engine;
     }
 }
diff --git a/gradle.properties b/gradle.properties
index 9743ae28f..b0beb83e1 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -34,9 +34,9 @@ commons_logging_version=1.2
 gson_version=2.10.1
 jna_version=5.13.0
 slf4j_version=1.7.36
-log4j_slf4j_version=2.22.0
-awssdk_version=2.20.121
-hadoop_version=3.3.5
+log4j_slf4j_version=2.22.1
+awssdk_version=2.22.12
+hadoop_version=3.3.6
 javacpp_version=1.5.9
 javacv_version=1.5.9
 ffmpeg_version=6.0-1.5.9
@@ -46,6 +46,6 @@ spark_version=3.3.2
 openpnp_opencv_version=4.7.0-0
 
 antlr_version=4.11.1
-testng_version=7.8.0
+testng_version=7.9.0
 junit_version=4.13.2
 mockito_version=5.3.1


Test patch:
diff --git a/api/src/test/java/ai/djl/DeviceTest.java b/api/src/test/java/ai/djl/DeviceTest.java
index 635728108..a69a50273 100644
--- a/api/src/test/java/ai/djl/DeviceTest.java
+++ b/api/src/test/java/ai/djl/DeviceTest.java
@@ -39,6 +39,7 @@ public class DeviceTest {
         System.setProperty("test_key", "test");
         Engine.debugEnvironment();
 
+        Assert.assertEquals(1, Device.cpu().getDevices().size());
         Assert.assertEquals(2, new MultiDevice(Device.gpu(1), Device.gpu(2)).getDevices().size());
     }
 
diff --git a/engines/pytorch/pytorch-engine/src/test/java/ai/djl/pytorch/integration/LibUtilsTest.java b/engines/pytorch/pytorch-engine/src/test/java/ai/djl/pytorch/integration/ALibUtilsTest.java
similarity index 73%
rename from engines/pytorch/pytorch-engine/src/test/java/ai/djl/pytorch/integration/LibUtilsTest.java
rename to engines/pytorch/pytorch-engine/src/test/java/ai/djl/pytorch/integration/ALibUtilsTest.java
index 617d2cfb8..f6cfda911 100644
--- a/engines/pytorch/pytorch-engine/src/test/java/ai/djl/pytorch/integration/LibUtilsTest.java
+++ b/engines/pytorch/pytorch-engine/src/test/java/ai/djl/pytorch/integration/ALibUtilsTest.java
@@ -18,17 +18,21 @@ import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
-public class LibUtilsTest {
+// Ensure this test run first
+public class ALibUtilsTest {
 
     @BeforeClass
     public void setup() {
-        System.setProperty(
-                "ai.djl.pytorch.native_helper", "ai.djl.pytorch.integration.LibUtilsTest");
+        System.setProperty("ai.djl.pytorch.native_helper", ALibUtilsTest.class.getName());
+        System.setProperty("STDCXX_LIBRARY_PATH", "/usr/lib/non-exists");
+        System.setProperty("PYTORCH_PRECXX11", "true");
     }
 
     @AfterClass
     public void teardown() {
         System.clearProperty("ai.djl.pytorch.native_helper");
+        System.clearProperty("LIBSTDCXX_LIBRARY_PATH");
+        System.clearProperty("PYTORCH_PRECXX11");
     }
 
     @Test
diff --git a/engines/tensorrt/src/test/java/ai/djl/tensorrt/engine/TrtEngineTest.java b/engines/tensorrt/src/test/java/ai/djl/tensorrt/engine/TrtEngineTest.java
index efd9d89e5..96066b380 100644
--- a/engines/tensorrt/src/test/java/ai/djl/tensorrt/engine/TrtEngineTest.java
+++ b/engines/tensorrt/src/test/java/ai/djl/tensorrt/engine/TrtEngineTest.java
@@ -26,7 +26,7 @@ public class TrtEngineTest {
         try {
             Engine engine = Engine.getEngine("TensorRT");
             version = engine.getVersion();
-        } catch (Throwable ignore) {
+        } catch (Exception ignore) {
             throw new SkipException("Your os configuration doesn't support TensorRT.");
         }
         Assert.assertEquals(version, "8.4.1");
diff --git a/engines/tensorrt/src/test/java/ai/djl/tensorrt/engine/TrtNDManagerTest.java b/engines/tensorrt/src/test/java/ai/djl/tensorrt/engine/TrtNDManagerTest.java
index 09001f0e2..24d734af5 100644
--- a/engines/tensorrt/src/test/java/ai/djl/tensorrt/engine/TrtNDManagerTest.java
+++ b/engines/tensorrt/src/test/java/ai/djl/tensorrt/engine/TrtNDManagerTest.java
@@ -28,7 +28,7 @@ public class TrtNDManagerTest {
         Engine engine;
         try {
             engine = Engine.getEngine("TensorRT");
-        } catch (Throwable ignore) {
+        } catch (Exception ignore) {
             throw new SkipException("Your os configuration doesn't support TensorRT.");
         }
         if (!engine.defaultDevice().isGpu()) {
diff --git a/engines/tensorrt/src/test/java/ai/djl/tensorrt/integration/TrtTest.java b/engines/tensorrt/src/test/java/ai/djl/tensorrt/integration/TrtTest.java
index 99cbc6f76..105e057ba 100644
--- a/engines/tensorrt/src/test/java/ai/djl/tensorrt/integration/TrtTest.java
+++ b/engines/tensorrt/src/test/java/ai/djl/tensorrt/integration/TrtTest.java
@@ -49,7 +49,7 @@ public class TrtTest {
         Engine engine;
         try {
             engine = Engine.getEngine("TensorRT");
-        } catch (Throwable ignore) {
+        } catch (Exception ignore) {
             throw new SkipException("Your os configuration doesn't support TensorRT.");
         }
         if (!engine.defaultDevice().isGpu()) {
@@ -75,7 +75,7 @@ public class TrtTest {
         Engine engine;
         try {
             engine = Engine.getEngine("TensorRT");
-        } catch (Throwable ignore) {
+        } catch (Exception ignore) {
             throw new SkipException("Your os configuration doesn't support TensorRT.");
         }
         if (!engine.defaultDevice().isGpu()) {
@@ -112,7 +112,7 @@ public class TrtTest {
         Engine engine;
         try {
             engine = Engine.getEngine("TensorRT");
-        } catch (Throwable ignore) {
+        } catch (Exception ignore) {
             throw new SkipException("Your os configuration doesn't support TensorRT.");
         }
         Device device = engine.defaultDevice();