当前位置: 首页 > 知识库问答 >
问题:

使用JTS解析WKB几何的不一致异常

西门展
2023-03-14

我遇到了一个最奇怪的问题,我就是无法理解。我的网络api使用Spring Boot和postgresql/postgis,在尝试从数据库中读取几何图形时出现了不一致的错误。我已经使用这段代码很多很多年了(当然偶尔会进行修改),这是我上一次发布时才开始发生的。

我在ubuntu 18.04上使用openjdk 11.0.4 2019-07-16 Releventspom.xml条目…

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

我从以下类型的api调用中得到各种错误...

例如六角弦: 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)

例如六弦: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)

例如六弦:0101000020E6100000666666669663C00D96D7371DD63440

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)

我的记录集代码的相关部分在下面(所以行号不会与上面的堆栈跟踪匹配)。

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;
        }
    }
}

所以最奇怪的是

  1. 它不会始终如一地发生。当我尝试重复它时,完全相同的api调用工作正常。
  2. 异常消息中报告的十六进制字符串是完全正确的!如果我使用相同的代码在测试程序中运行它们,请给出正确的答案,没有例外。

同样,上述所有导致生产api调用错误的十六进制字符串都是POINT几何图形的有效表示。

这是一些奇怪的潜在内存泄漏问题吗?

共有1个答案

轩辕嘉平
2023-03-14

也许这应该是显而易见的,但为我辩护,我已经使用上述代码很多年了(如我所说),没有问题,所以我认为我只是忽略了显而易见的东西?无论如何,我突然意识到我应该在多线程环境中反复使用相同的WKBReader吗?嗯,结果证明不是!

如果我只是在每次调用时创建一个新的WBBReader()(而不是获取一个静态的WKBReader),它就可以正常工作。嗯,这就是我“内存泄漏”的根源。自己造成的!

 类似资料:
  • 我正在尝试将旧的EJB服务(其中的逻辑)包装在一个微服务中。我使用Quarkus/RESTEasy实现此微服务 但是,我在自定义序列化/反序列化时遇到问题。 问题:,这让我相信Jackson并不认为Geometry是要解析为String的类。这让我相信对象映射器没有被拾取。。 注1:我可以在Quarkus日志中提供的日志语句中看到: 注2:单元测试在上运行良好。 这是我要解析的JSON(注:几何是

  • 问题内容: 我真的很head头。我使用s已有一段时间了,但现在,使用SimpleDateFormat解析日期(只是有时)是完全错误的。 特别: 打印字符串。有没有搞错?-它甚至都不会一直解析为错误的日期! 更新: 修复得很漂亮。您不知道吗,在其他一些地方也滥用了它。一定喜欢调试别人的代码:) 问题答案: 我认为您要使用格式,而不是’hh’,以便您使用00-23之间的小时数。“ hh”采用12小时增

  • 在我刚刚编写的一个测试解析器中,我遇到了一个奇怪的问题,我不太明白。 将其简化为显示问题的最小示例,让我们从以下语法开始: 这是语法的变化: 突然间,相同的测试输入被错误地分解成两个statement_list,每个statement_list都继续到一个带有“missing”;“警告,第一个返回“z=”的不完整的assignment_statement,第二个返回“x+”的不完整的assignm

  • Hibernate-spatial 5.4.22, hibernate.dialect = org.hibernate.spatial.dialect.postgis.PostgisDialect 一个非常简单的查询: 边界几何通过以下方式生成: 但它产生误差 所以似乎捡到了postgis形状字段是几何学的。(它是postgis几何类型),但无法理解JTS几何对象。我看到很多关于反面的问题,但不是

  • 我需要解析一个日期,当我解析一个无效的日期“2007年2月29日”时,它将以dd/MM/yyyy的格式返回给我,作为本地日期2007-02-28,代码如下: 但是,如果我使用ISO格式(没有DateTimeFormatter)进行解析,则会出现异常,代码如下: 例外情况: 所以我的问题是,我想考虑一下: 由于无效,我如何使用LocalDate呢。作语法分析