<!DOCTYPE html><html><head><title></title></head><body><div>Hi Evan</div><div><br></div><div>I seem to still be having problems closing datasets in Java resulting in a JVM crash, using gdal-3-13-3_x64 downloaded from the GISInternals site.  Below is the stack trace information. <br></div><div><div><br></div><div>---------------  T H R E A D  ---------------</div><div><br></div><div>Current thread (0x000001ffd39932c0):  JavaThread "Finalizer" daemon [_thread_in_native, id=25140, stack(0x000000ba6eb00000,0x000000ba6ec00000) (1024K)]</div><div><br></div><div>Stack: [0x000000ba6eb00000,0x000000ba6ec00000],  sp=0x000000ba6ebfed60,  free space=1019k</div><div>Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)</div><div>C  [gdal.dll+0xc86927]</div><div><br></div><div>Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)</div><div>j  org.gdal.gdal.gdalJNI.delete_Dataset(J)V+0</div><div>j  org.gdal.gdal.Dataset.delete()V+25</div><div>j  org.gdal.gdal.Dataset.finalize()V+1</div><div>j  java.lang.System$2.invokeFinalize(Ljava/lang/Object;)V+1 java.base@21.0.6</div><div>j  java.lang.ref.Finalizer.runFinalizer(Ljdk/internal/access/JavaLangAccess;)V+115 java.base@21.0.6</div><div>j  java.lang.ref.Finalizer$FinalizerThread.run()V+29 java.base@21.0.6</div><div>v  ~StubRoutines::call_stub 0x000001ffa369100d</div><div><br></div><div>siginfo: EXCEPTION_ACCESS_VIOLATION (0xc0000005), reading address 0xffffffffffffffff<br></div><div><br></div><div> The crash is happening when the swig delete_Dataset method, called by the finalizer, calls into the gdal.dll.</div><div><br></div></div><div>I tried calling Open() and Close() several times in a row to see if this would trigger the problem, like this:</div><div>gdal.<i>AllRegister</i>();</div><div> Dataset ds = gdal.Open(filename); </div><div> ds.Close();</div><div> ds.Close();  </div><div><br></div><div>but that seemed to work ok.</div><div><br></div><div>I also tried open and close sequences, like this:</div><div> Dataset ds = gdal.Open(filename);</div><div> ds.Close();</div><div> ds = gdal.Open(filename);<br></div><div> ds.Close();  </div><div> ds = gdal.Open(filename);</div><div> System.gc();</div><div> System.runFinalization();</div><div><br></div><div>This didn't trigger a problem either.  I did a few more tests, repeating steps of opening a dataset, reading a band, closing the dataset, and this didn't do it either.</div><div><br></div><div>If I enable CPL_DEBUG then my pattern of access that causes the crash is:</div><div>GDAL: GDALDriver::Create(GTiff,c:/tmp/test1.tif,10,10,1,Int32,000001BCB9893680)</div><div>GDAL: GDALClose(c:/tmp/test1.tif, this=000001BCB9872A90)</div><div>GDAL: GDALOpen(c:/tmp/test1.tif, this=000001BCB98784D0) succeeds as GTiff.</div><div>GDAL: GDALClose(c:/tmp/test1.tif, this=000001BCB98784D0)</div><div>GDAL: GDALOpen(c:/tmp/test1.tif, this=000001BCBE486550) succeeds as GTiff.</div><div>GDAL: GDALOpen(c:/tmp/test1.tif.vat.dbf, this=000001BCBE10D070) succeeds as ESRI Shapefile.</div><div>GDAL: GDALClose(c:/tmp/test1.tif.vat.dbf, this=000001BCBE10D070)</div><div>GDAL: GDALClose(c:/tmp/test1.tif, this=000001BCBE486550)</div><div><br></div><div><div>Around this point the finalizer kicks in and the JVM crashes.</div><div><br></div></div><div>This is a hard one for me to track down, because I don't know the tooling to debug native cpp code from within Java.  What I could do is insert some debugging statements in to the code to try to see what is going on.  If you have any suggestions about this I would be happy to try it.</div><div><br></div><div>Tom</div><div><br></div><div><br></div><div>On Fri, May 30, 2025, at 5:53 PM, Even Rouault wrote:</div><blockquote type="cite" id="qt" style=""><div><br></div><div>Le 30/05/2025 à 23:39, Tom Moore a écrit :</div><div>> Hi Even</div><div>></div><div>> I just wanted to update you and provide a record for posterity with </div><div>> the results of me playing around with gdal/java and resource management.</div><div>></div><div>> It appears to me that Dataset objects should not be closed from Java </div><div>> client code.  If you do then often there will be an access violation </div><div>> (native null pointer) that will crash the JVM. From the dump file the </div><div>> following stack trace shows the Java code being executed when the </div><div>> exception occurs:</div><div><br></div><div>I believe this issue should be fixed in 3.11.0 per </div><div><a href="https://github.com/OSGeo/gdal/commit/ec4ca7930b48653bb0fac27b59c6c1bf883c45f2">https://github.com/OSGeo/gdal/commit/ec4ca7930b48653bb0fac27b59c6c1bf883c45f2</a></div><div><br></div><div>Actually historically this was the .delete() method that should be </div><div>called. The exposition of .Close() is quite recent and was broken (until </div><div>the above mentioned fix)</div><div><br></div><div>></div><div>> Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)</div><div>> j  org.gdal.gdal.gdalJNI.delete_Dataset(J)V+0</div><div>> j  org.gdal.gdal.Dataset.delete()V+25</div><div>> j  org.gdal.gdal.Dataset.finalize()V+1</div><div>> j  java.lang.System$2.invokeFinalize(Ljava/lang/Object;)V+1 </div><div>> java.base@21.0.6</div><div>> j </div><div>> java.lang.ref.Finalizer.runFinalizer(Ljdk/internal/access/JavaLangAccess;)V+115 </div><div>> java.base@21.0.6</div><div>> j  java.lang.ref.Finalizer$FinalizerThread.run()V+29 java.base@21.0.6</div><div>></div><div>> So it looks like the swig bindings implement a finalizer to dispose of </div><div>> the native object when the reference is no longer reachable (nice!).  </div><div>> However it looks like there might not be any protection to prevent bad </div><div>> things from happening when the Delete method is called more than </div><div>> once.  It appears that in this case that when the finalizer calls </div><div>> Delete on the Dataset the jvm crashes because the Dataset has already </div><div>> been closed manually and the resources have already been released.</div><div>></div><div>> If I am correct in this conclusions then this is not a problem.  If </div><div>> correct I suggest that either the docs be updated to indicate do not </div><div>> manually call Delete on the Dataset object, or change the Delete </div><div>> method code to gracefully handle multiple calls (better choice).</div><div>></div><div>> By the way, something to note for the future is that finalizers have </div><div>> been deprecated since Java 9 (2017).  This is described in </div><div>> <a href="https://openjdk.org/jeps/421">https://openjdk.org/jeps/421</a>. Although deprecated, finalizers are </div><div>> still allowed in modern jdk's and probably will be for a while yet. At </div><div>> some future time they will be removed.  The suggested replacement for </div><div>> finalizers are cleaners, but they are only available in Java 9+.  When </div><div>> finalizers are removed there will need to be a new set of bindings </div><div>> that use cleaners.  You can probably ignore this problem for a few </div><div>> more years, but at some point you will need to provide two sets of </div><div>> Java bindings (one required for Java 8 and earlier, and one required </div><div>> for some future Java and later).</div><div><br></div><div>Thanks for the heads up. Seizing the opportunity to remind interesting </div><div>parties in the GDAL Java bindings that they should not be shy and are </div><div>welcome to be proactive. On my side, they are very very minimilastically </div><div>maintained.</div><div><br></div><div>Even</div><div><br></div><div>-- </div><div><a href="http://www.spatialys.com">http://www.spatialys.com</a></div><div>My software is free, but my time generally not.</div><div><br></div><div><br></div></blockquote><div><br></div><div id="sig151763583"><div class="signature">--</div><div class="signature">Tom Moore</div><div class="signature">Spatial Planning Systems</div><div class="signature">960 Burkes Bluff Lane</div><div class="signature">Deep River ON  K0J 1P0</div><div class="signature">Canada</div><div class="signature"><br></div><div class="signature">Phone: +1 613 584 9354</div></div><div><br></div></body></html>