简体   繁体   中英

Circular reference - Gson StackOverflowError

I am having trouble to figure out why saving the following object to a .json file with Gson throws a StackOverflowError . Am I having a circular reference somewhere?

This is the object I am trying to save with 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

}

The class LocationConfig uses the following Warp class in its HashSet warps :

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

}

I am using the following to save an LocationConfig Object:

// 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();
    }

}

The error I get while performing 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

Thank you!

The problem was, that I was using the Location class of a Minecraft Server API called Spigot. In order to solve the problem I had to use a much simpler Location object than the provided one.

As mentioned in the comments :

Usual suspects for this error are either circular references or unknowingly put complex objects

The solution for me was this SimpleLocation class, because it does not contain any complex references:

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

}

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