简体   繁体   中英

Inconsistent Exception parsing WKB geometry using JTS

I am getting the strangest problem that I just can't wrap my head around. My web api which uses Spring Boot and postgresql/postgis, is getting inconsistent errors when trying to read geometries from the database. I have been using this code (with occasional modifications of course) for many, many years and this just starting happening on my last release.

I am using openjdk 11.0.4 2019-07-16 on ubuntu 18.04. Relevent pom.xml entries ...

        <groupId>org.locationtech.jts</groupId>
            <artifactId>jts-core</artifactId>
            <version>1.16.1</version>
        </dependency>

I am getting various errors from api calls of the following types ...

eg hexstring: 0101000020E6100000795C548B88184FC0206118B0E42750C0

org.locationtech.jts.io.ParseException: Unknown WKB type 0
    at org.locationtech.jts.io.WKBReader.readGeometry(WKBReader.java:235)
    at org.locationtech.jts.io.WKBReader.read(WKBReader.java:156)
    at org.locationtech.jts.io.WKBReader.read(WKBReader.java:137)
    at net.crowmagnumb.database.RecordSet.getGeom(RecordSet.java:1073)

eg hexstring: 0101000020E61000000080FB3F354F5AC0F3D30EF2C0773540

java.lang.ArrayIndexOutOfBoundsException: arraycopy: length -1 is negative
    at java.base/java.lang.System.arraycopy(Native Method)
    at org.locationtech.jts.io.ByteArrayInStream.read(ByteArrayInStream.java:59)
    at org.locationtech.jts.io.ByteOrderDataInStream.readDouble(ByteOrderDataInStream.java:83)
    at org.locationtech.jts.io.WKBReader.readCoordinate(WKBReader.java:378)
    at org.locationtech.jts.io.WKBReader.readCoordinateSequence(WKBReader.java:345)
    at org.locationtech.jts.io.WKBReader.readPoint(WKBReader.java:256)
    at org.locationtech.jts.io.WKBReader.readGeometry(WKBReader.java:214)
    at org.locationtech.jts.io.WKBReader.read(WKBReader.java:156)
    at org.locationtech.jts.io.WKBReader.read(WKBReader.java:137)
    at net.crowmagnumb.database.RecordSet.getGeom(RecordSet.java:1073)

eg hexstring: 0101000020E610000066666666669663C00D96D7371DD63440

org.locationtech.jts.io.ParseException: Unknown WKB type 326
    at org.locationtech.jts.io.WKBReader.readGeometry(WKBReader.java:235)
    at org.locationtech.jts.io.WKBReader.read(WKBReader.java:156)
    at org.locationtech.jts.io.WKBReader.read(WKBReader.java:137)
    at net.crowmagnumb.database.RecordSet.getGeom(RecordSet.java:1073)

The relevant parts of my RecordSet code is below (so line numbers will not match above stack traces).

public class RecordSet {
    private static final Logger logger = LoggerFactory.getLogger(RecordSet.class);
    private static WKBReader wkbReader;

    private static WKBReader getWKBReader() {
        if (wkbReader == null) {
            wkbReader = new WKBReader();
        }
        return wkbReader;
    }

    private static byte[] hexStringToByteArray(final String hex) {
        if (StringUtils.isBlank(hex)) {
            return null;
        }

        int len = hex.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4) + Character.digit(hex.charAt(i + 1), 16));
        }
        return data;
    }

    public static Geometry getGeom(final String geomStr) {
        byte[] byteArray = hexStringToByteArray(geomStr);
        if (byteArray == null) {
            return null;
        }
        try {
            return getWKBReader().read(byteArray);
        } catch (Throwable ex) {
            logger.error(String.format("Error parsing geometry [%s]", geomStr), ex);
            return null;
        }
    }
}

So the extreme weirdness is that

  1. It doesn't happen consistently. The exact same api call when I try to repeat it works fine.
  2. The reported hex strings in the exception message are perfectly correct! If I run them in a test program using the same code give the correct answer and no exception.

Again all of the above reported hexstrings that lead to errors in production api calls are valid representations of POINT geometries.

Is this some weird potential memory leak issue?

Maybe this should have been obvious but in my defense I have been using the above code for many, many years (as I said) without issue so I think I just overlooked the obvious? Anyway, it suddenly dawned on me should I be reusing the same WKBReader over and over again in a multiple-threaded environment? Well, turns out no!

If I just create a new WBBReader() with each call (instead of getting a single static WKBReader) it works fine. Well there is the source of my "memory leak". Self caused!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM