【问题标题】:Circular reference - Gson StackOverflowError循环参考 - Gson StackOverflowError
【发布时间】:2019-12-27 15:53:21
【问题描述】:

我无法弄清楚为什么使用 Gson 将以下对象保存到 .json 文件会引发 StackOverflowError。我在某处有循环引用吗?

这是我试图用 Gson 保存的对象:

public class LocationConfig {

    private HashSet<Warp> warps = new HashSet<>();

    public LocationConfig() {
        warps.add(new Warp("placeholder", false, new Location(Bukkit.getWorld("world"), 0, 0, 0)));
    }

    // getter and setter

}

LocationConfig 类在其 HashSet warps 中使用以下 Warp 类:

public class Warp {

    private String name;
    private boolean ifListed;
    private Location loc;

    public Warp(String name, boolean ifListed, Location loc) {
        this.name = name;
        this.ifListed = ifListed;
        this.loc = loc;
    }

    // getter and setter

}

我正在使用以下内容来保存LocationConfig 对象:

// config is an object of the type LocationConfig
if (config != null) {

    Gson gson = new GsonBuilder().setPrettyPrinting().create();

    try (FileWriter writer = new FileWriter(path)) {
        gson.toJson(config, writer);
    } catch (IOException e) {
        e.printStackTrace();
    }

}

我在执行gson.toJson(config, writer)时遇到的错误:

[16:12:42] [Server thread/WARN]: java.lang.StackOverflowError
[16:12:42] [Server thread/WARN]:    at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:383)
[16:12:42] [Server thread/WARN]:    at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:378)
repeating very often
[16:12:42] [Server thread/WARN]:    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:158)
[16:12:42] [Server thread/WARN]:    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100)
[16:12:42] [Server thread/WARN]:    at com.google.gson.Gson.getAdapter(Gson.java:423)
[16:12:42] [Server thread/WARN]:    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:115)
[16:12:42] [Server thread/WARN]:    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:164)
[16:12:42] [Server thread/WARN]:    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100)
[16:12:42] [Server thread/WARN]:    at com.google.gson.Gson.getAdapter(Gson.java:423)
repeating very often

谢谢!

【问题讨论】:

  • 您的 Location 类是否包含对 Warp 的引用?你也能描述一下Location吗?
  • @AdwaitKumar Location 绝对不包含对 Warp 的引用。 Location 包含双精度 (x,y,z)、一个描述方向的向量和一个 World 对象(也不以任何方式引用 Warp)。
  • 可能包含对配置的引用
  • @KarimSNOUSSI 不要LocationConfig
  • location 是否有这个或者那个暴露整个类引用树是个好主意。喜欢LocationWorld。也许可能的循环引用无论如何都与任何显示的类无关。也许它是在其他一些课程之间。那么,可能的回答者如何重现这个问题呢?

标签: java gson


【解决方案1】:

问题是,我正在使用名为 Spigot 的 Minecraft 服务器 API 的 Location 类。为了解决这个问题,我不得不使用比提供的更简单的 Location 对象。

comments中提到的:

这个错误的通常嫌疑人要么是循环引用,要么是在不知不觉中放置了复杂的对象

我的解决方案是这个SimpleLocation 类,因为它不包含任何复杂的引用:

import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.util.Vector;

public class SimpleLocation {

    private double x;
    private double y;
    private double z;
    private Vector direction;
    private String worldname;

    public SimpleLocation(String worldname, double x, double y, double z, Vector direction) {
        this.x = x;
        this.y = y;
        this.z = z;
        this.direction = direction;
        this.worldname = worldname;
    }

    public SimpleLocation(Location loc) {
        this.x = loc.getX();
        this.y = loc.getY();
        this.z = loc.getZ();
        this.direction = loc.getDirection();
        if (loc.getWorld() != null) {
            this.worldname = loc.getWorld().getName();
        } else {
            throw new NullPointerException("The locations world is null!");
        }
    }

    public Location getLocation() {
        return new Location(Bukkit.getWorld(worldname), x, y, z).setDirection(direction);
    }

    public double getX() {
        return x;
    }

    public void setX(double x) {
        this.x = x;
    }

    public double getY() {
        return y;
    }

    public void setY(double y) {
        this.y = y;
    }

    public double getZ() {
        return z;
    }

    public void setZ(double z) {
        this.z = z;
    }

    public Vector getDirection() {
        return direction;
    }

    public void setDirection(Vector direction) {
        this.direction = direction;
    }

    public String getWorldname() {
        return worldname;
    }

    public void setWorldname(String worldname) {
        this.worldname = worldname;
    }

}

【讨论】:

    猜你喜欢
    • 2012-11-08
    • 1970-01-01
    • 1970-01-01
    • 2014-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-01
    相关资源
    最近更新 更多