OSGeo / gdal

GDAL is an open source MIT licensed translator library for raster and vector geospatial data formats.
https://gdal.org
Other
4.83k stars 2.53k forks source link

Java ReadRaster(): Is there a need for initialization after malloc? #8963

Open tthh7 opened 10 months ago

tthh7 commented 10 months ago

I use Java to call GDAL for reading raster data, and then initialize a Java array to store the raster data. However, when I pass this array to the C++ interface, the content inside the array is not the initial value. So, during debugging, I found that the data from the Java array is not copied; instead, a temporary data is generated using malloc and passed to the C++ interface for reading the raster dataset. The code is as follows: swig/java/gdal_warp.cpp arg10 = sizeof(char) jenv->GetArrayLength(jarg9); arg9 = (char) malloc(arg10); //arg9 = (char) jenv->GetPrimitiveArrayCritical(jarg9, 0); if (arg9 == NULL) { SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, "Unable to allocate temporary buffer."); return 0; } } { / %typemap(in) (int nList, int pList) / / check if is List / if (jarg11) { arg11 = jenv->GetArrayLength(jarg11); if (arg11 == 0) arg12 = NULL; else arg12 = (int *)jenv->GetIntArrayElements(jarg11, NULL); } else { arg11 = 0; arg12 = NULL; } } arg13 = (int)jarg13; arg14 = (int)jarg14; arg15 = (int)jarg15; result = (CPLErr)GDALDatasetShadow_ReadRaster__SWIG_0(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14,arg15);

Steps to reproduce the problem.

In the above code, is it necessary to initialize after malloc? Why not directly use the array passed in from Java?

Operating system

centos7

GDAL version and provenance

gdal 2.2.3

rouault commented 10 months ago

In the above code, is it necessary to initialize after malloc?

hum.. if you pass a fully contiguous array (that is nPixelSpace, nLineSpace, nBandSpace describe a contiguous array), this should'nt be necessary. But if not, then the issue is more than the SetByteArrayRegion() after GDALDatasetShadow_ReadRaster__SWIG_0() will overwrite elements it shouldn't.

Why not directly use the array passed in from Java?

I believe the issue is that otherwise we need to call a JNI primitive GetPrimitiveArrayCritical() which blocks JNI for other threads.

Rather than using ReadRaster(), I'd suggest ReadRaster_Direct() : https://gdal.org/java/org/gdal/gdal/Dataset.html#ReadRaster_Direct(int,int,int,int,int,int,int,java.nio.ByteBuffer,int%5B%5D)