Repository: deepjavalibrary/djl (java)

Issue:
Core dump when trying to create empty IValue list for pytorch engine
## Description

Core dump when trying to create an empty IValue list with `IValue.listFrom(new IValue[0])` with djl 0.14.0

However `IValue.listFrom(new double[0])` works for creating an empty double list

### Expected Behavior

It should successfully create an IValue instance which represents an empty list of IValues.

### Error Message

Core dump

From JVM thread dump
```
Register to memory mapping:

RAX=0x0000000000000000 is an unknown value
RBX={method} {0x00007fa45f747a20} 'iValueFromList' '([J)J' in 'ai/djl/pytorch/jni/PyTorchLibrary'
RCX=0x00007fa48b3c4207: mprotect+0x7 in /lib/x86_64-linux-gnu/libc.so.6 at 0x00007fa48b2d0000
RDX=0x0000000000000000 is an unknown value
RSP=0x00007fa48a1301b0 is pointing into the stack for thread: 0x00007fa48400a800
RBP=0x00007fa48a1302f0 is pointing into the stack for thread: 0x00007fa48400a800
RSI=0x0000000000000000 is an unknown value
RDI=0x00007fa48a130290 is pointing into the stack for thread: 0x00007fa48400a800
R8 =0x00000000ffffffff is an unknown value
R9 =0x0000000000000000 is an unknown value
R10=0x0000000000004022 is an unknown value
R11=0x0000000000000206 is an unknown value
R12=0x0000000000000000 is an unknown value
R13={method} {0x00007fa45f747a20} 'iValueFromList' '([J)J' in 'ai/djl/pytorch/jni/PyTorchLibrary'
R14=0x00007fa48a130378 is pointing into the stack for thread: 0x00007fa48400a800
R15=0x00007fa48400a800 is a thread


Stack: [0x00007fa48a033000,0x00007fa48a133000],  sp=0x00007fa48a1301b0,  free space=1012k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [libtorch_cpu.so+0xef892a]  c10::IValue::type() const+0x1a
j  ai.djl.pytorch.jni.PyTorchLibrary.iValueFromList([J)J+0
j  ai.djl.pytorch.jni.IValue.listFrom([Lai/djl/pytorch/jni/IValue;)Lai/djl/pytorch/jni/IValue;+28
```

## How to Reproduce?

```
IValue emptyList = IValue.listFrom(new IValue[0]);
```

### Steps to reproduce

Simply run the above code from java

## What have you tried to solve it?

looks like it's an issue with the JNI layer, so not much i can do without changing it.

## Environment Info

```
--------------- Hardware --------------
Available processors (cores): 4
Byte Order: LITTLE_ENDIAN
Free memory (bytes): 210618976
Maximum memory (bytes): 3663200256
Total memory available to JVM (bytes): 247463936
Heap committed: 247463936
Heap nonCommitted: 30212096
GCC: 
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
```


Pull request:
[pytorch] Fixes #1437, check empty IValue[]
Change-Id: If6bebfef02efb1d42b65b1dd58b591df8274ff24

## 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/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/jni/IValue.java b/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/jni/IValue.java
index 472c6bdde..45b5866d9 100644
--- a/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/jni/IValue.java
+++ b/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/jni/IValue.java
@@ -250,6 +250,9 @@ public class IValue extends NativeResource<Long> {
      * @return a new {@code IValue} of type {@code NDArray[]}
      */
     public static IValue listFrom(IValue... list) {
+        if (list.length == 0) {
+            throw new IllegalArgumentException("Empty IValue list is not supported.");
+        }
         long[] tensors = Arrays.stream(list).mapToLong(IValue::getHandle).toArray();
         return new IValue(PyTorchLibrary.LIB.iValueFromList(tensors));
     }


Test patch:
diff --git a/engines/pytorch/pytorch-engine/src/test/java/ai/djl/pytorch/integration/IValueTest.java b/engines/pytorch/pytorch-engine/src/test/java/ai/djl/pytorch/integration/IValueTest.java
index bb4f78b38..eebf7a159 100644
--- a/engines/pytorch/pytorch-engine/src/test/java/ai/djl/pytorch/integration/IValueTest.java
+++ b/engines/pytorch/pytorch-engine/src/test/java/ai/djl/pytorch/integration/IValueTest.java
@@ -137,6 +137,7 @@ public class IValueTest {
                 NDList list = ivalue.toNDList(manager);
                 Assert.assertEquals(list.size(), 3);
             }
+            Assert.assertThrows(() -> IValue.listFrom(new IValue[0]));
 
             try (IValue iv1 = IValue.from(array1);
                     IValue iv2 = IValue.from(array2);