Call close on Tensor objects to release memory
diff --git a/tf-ner-poc/src/main/java/org/apache/opennlp/namefinder/FeedDictionary.java b/tf-ner-poc/src/main/java/org/apache/opennlp/namefinder/FeedDictionary.java
index 26293ef..c8fae3b 100644
--- a/tf-ner-poc/src/main/java/org/apache/opennlp/namefinder/FeedDictionary.java
+++ b/tf-ner-poc/src/main/java/org/apache/opennlp/namefinder/FeedDictionary.java
@@ -17,40 +17,25 @@
 
 package org.apache.opennlp.namefinder;
 
-import org.tensorflow.Tensor;
-
 import java.util.Arrays;
 
-public class FeedDictionary {
+import org.tensorflow.Tensor;
+
+public class FeedDictionary implements AutoCloseable  {
 
   static int PAD_VALUE = 0;
 
 
-  private final float dropout;
-  private final int[][][] charIds;
-  private final int[][] wordLengths;
-  private final int[][] wordIds;
+  private final Tensor<Float> dropoutTensor;
+  private final Tensor<Integer> charIdsTensor;
+  private final Tensor<Integer> wordLengthsTensor;
+  private final Tensor<Integer> wordIdsTensor;
   private final int[] sentenceLengths;
+  private final Tensor<Integer> sentenceLengthsTensor;
   private final int maxSentenceLength;
   private final int maxCharLength;
   private final int numberOfSentences;
 
-  public float getDropout() {
-    return dropout;
-  }
-
-  public int[][][] getCharIds() {
-    return charIds;
-  }
-
-  public int[][] getWordLengths() {
-    return wordLengths;
-  }
-
-  public int[][] getWordIds() {
-    return wordIds;
-  }
-
   public int[] getSentenceLengths() {
     return sentenceLengths;
   }
@@ -59,32 +44,29 @@
     return maxSentenceLength;
   }
 
-  public int getMaxCharLength() {
-    return maxCharLength;
-  }
-
   public int getNumberOfSentences() {
     return numberOfSentences;
   }
 
-  public Tensor<Integer> getSentenceLengthsTensor() {
-    return Tensor.create(sentenceLengths, Integer.class);
-  }
-
   public Tensor<Float> getDropoutTensor() {
-    return Tensor.create(dropout, Float.class);
+    return dropoutTensor;
   }
 
   public Tensor<Integer> getCharIdsTensor() {
-    return Tensor.create(charIds, Integer.class);
+    return charIdsTensor;
   }
 
+  public Tensor<Integer> getSentenceLengthsTensor() {
+    return sentenceLengthsTensor;
+  }
+
+
   public Tensor<Integer> getWordLengthsTensor() {
-    return Tensor.create(wordLengths, Integer.class);
+    return wordLengthsTensor;
   }
 
   public Tensor<Integer> getWordIdsTensor() {
-    return Tensor.create(wordIds, Integer.class);
+    return wordIdsTensor;
   }
 
   private FeedDictionary(final float dropout,
@@ -96,17 +78,26 @@
                          final int maxCharLength,
                          final int numberOfSentences) {
 
-    this.dropout = dropout;
-    this.charIds = charIds;
-    this.wordLengths = wordLengths;
-    this.wordIds = wordIds;
+    dropoutTensor = Tensor.create(dropout, Float.class);
+    charIdsTensor = Tensor.create(charIds, Integer.class);
+    wordLengthsTensor = Tensor.create(wordLengths, Integer.class);
+    wordIdsTensor = Tensor.create(wordIds, Integer.class);
     this.sentenceLengths = sentenceLengths;
+    sentenceLengthsTensor = Tensor.create(sentenceLengths, Integer.class);
     this.maxSentenceLength = maxSentenceLength;
     this.maxCharLength = maxCharLength;
     this.numberOfSentences = numberOfSentences;
 
   }
 
+  public void close() {
+    dropoutTensor.close();
+    charIdsTensor.close();
+    wordLengthsTensor.close();
+    wordIdsTensor.close();
+    sentenceLengthsTensor.close();
+  }
+
   // multi sentences
   public static FeedDictionary create(TokenIds sentences) {
 
diff --git a/tf-ner-poc/src/main/java/org/apache/opennlp/namefinder/SequenceTagging.java b/tf-ner-poc/src/main/java/org/apache/opennlp/namefinder/SequenceTagging.java
index 69a1748..5f3d513 100644
--- a/tf-ner-poc/src/main/java/org/apache/opennlp/namefinder/SequenceTagging.java
+++ b/tf-ner-poc/src/main/java/org/apache/opennlp/namefinder/SequenceTagging.java
@@ -32,9 +32,7 @@
 import org.tensorflow.Tensor;
 
 import opennlp.tools.namefind.BioCodec;
-import opennlp.tools.namefind.NameSample;
 import opennlp.tools.namefind.TokenNameFinder;
-import opennlp.tools.tokenize.SimpleTokenizer;
 import opennlp.tools.util.Span;
 
 public class SequenceTagging implements TokenNameFinder, AutoCloseable {
@@ -87,8 +85,13 @@
 
   @Override
   public Span[] find(String[] sentence) {
-    TokenIds tokenIds = wordIndexer.toTokenIds(sentence);
-    return new BioCodec().decode(Arrays.asList(predict(tokenIds)[0]));
+    if (sentence.length > 0) {
+      TokenIds tokenIds = wordIndexer.toTokenIds(sentence);
+      return new BioCodec().decode(Arrays.asList(predict(tokenIds)[0]));
+    }
+    else {
+      return new Span[0];
+    }
   }
 
   public String[][] predict(String[][] sentences) {
@@ -97,31 +100,42 @@
   }
 
   private String[][] predict(TokenIds tokenIds) {
-    FeedDictionary fd = FeedDictionary.create(tokenIds);
 
-    List<Tensor<?>> run = session.runner()
-            .feed("chars/char_ids:0", fd.getCharIdsTensor())
-            .feed("dropout_keep_prop:0", fd.getDropoutTensor())
-            .feed("words/sequence_lengths:0", fd.getSentenceLengthsTensor())
-            .feed("words/word_ids:0", fd.getWordIdsTensor())
-            .feed("chars/word_lengths:0", fd.getWordLengthsTensor())
-            .fetch("logits", 0)
-            .fetch("trans_params", 0).run();
+    try (FeedDictionary fd = FeedDictionary.create(tokenIds)) {
 
-    float[][][] logits = new float[fd.getNumberOfSentences()][fd.getMaxSentenceLength()][indexTagger.getNumberOfTags()];
-    run.get(0).copyTo(logits);
+      List<Tensor<?>> run = session.runner()
+          .feed("chars/char_ids:0", fd.getCharIdsTensor())
+          .feed("dropout_keep_prop:0", fd.getDropoutTensor())
+          .feed("words/sequence_lengths:0", fd.getSentenceLengthsTensor())
+          .feed("words/word_ids:0", fd.getWordIdsTensor())
+          .feed("chars/word_lengths:0", fd.getWordLengthsTensor())
+          .fetch("logits", 0)
+          .fetch("trans_params", 0).run();
 
-    float[][] trans_params = new float[indexTagger.getNumberOfTags()][indexTagger.getNumberOfTags()];
-    run.get(1).copyTo(trans_params);
+      float[][][] logits = new float[fd.getNumberOfSentences()][fd.getMaxSentenceLength()][indexTagger.getNumberOfTags()];
+      run.get(0).copyTo(logits);
 
-    String[][] returnValue = new String[fd.getNumberOfSentences()][];
-    for (int i=0; i < logits.length; i++) {
-      //logit = logit[:sequence_length] # keep only the valid steps
-      float[][] logit = Arrays.copyOf(logits[i], fd.getSentenceLengths()[i]);
-      returnValue[i] = Viterbi.decode(logit, trans_params).stream().map(indexTagger::getTag).toArray(String[]::new);
+      float[][] trans_params = new float[indexTagger.getNumberOfTags()][indexTagger.getNumberOfTags()];
+      run.get(1).copyTo(trans_params);
+
+      String[][] returnValue = new String[fd.getNumberOfSentences()][];
+      for (int i = 0; i < logits.length; i++) {
+        float[][] logit = Arrays.copyOf(logits[i], fd.getSentenceLengths()[i]);
+        returnValue[i] = Viterbi.decode(logit, trans_params).stream().map(indexTagger::getTag).toArray(String[]::new);
+      }
+
+      for (int i = 0; i < returnValue[0].length; i++) {
+        if (returnValue[0][i] == null) {
+          returnValue[0][i] = "other";
+        }
+      }
+
+      for (Tensor t : run) {
+        t.close();
+      }
+
+      return returnValue;
     }
-
-    return returnValue;
   }
 
   @Override