StackOverflowError異常處理

 在java虛擬機規範中,虛擬機棧和本地方法棧都會出現StackOverflowError和OutofMemoryError,程序計數器是java虛擬機中唯一一塊不會產生error的內存區域,StackOverflowError代表的是,當棧深度超過虛擬機分配給線程的棧大小時就會出現此error,OutofMemoryError代表的是,當再申請新的內存時,虛擬機分配給線程的內存大小中無法再分配新的內存,就會出現此error。

現象:對象互相嵌套設置出現StackOverflowError異常

對象A:

package com.test;

import com.wordnik.swagger.annotations.ApiModel;
import com.wordnik.swagger.annotations.ApiModelProperty;

import java.io.Serializable;
import java.util.List;

/**
 * test-manager
 * Created by xian.juanjuan on 2017-5-11 16:25.
 */
@ApiModel(description = "test-manager   Created by xian.juanjuan on 2017-5-11 16:25.")
public class Student implements Serializable{

    private static final long serialVersionUID = -4895104060364320456L;
    /**
     * 用戶ID
     */
    @ApiModelProperty(value = "用戶ID")
    private String userId;

    /**
     * 用戶名
     */
    @ApiModelProperty(value = "用戶名")
    private String userName;

    /**
     * 分數
     */
    @ApiModelProperty(value = "分數")
    private List<Score> scores;


    /**
     * 獲取 用戶ID
     */
    public String getUserId() {
        return this.userId;
    }

    /**
     * 設置 用戶ID
     */
    public void setUserId(String userId) {
        this.userId = userId;
    }

    /**
     * 獲取 用戶名
     */
    public String getUserName() {
        return this.userName;
    }

    /**
     * 設置 用戶名
     */
    public void setUserName(String userName) {
        this.userName = userName;
    }

    /**
     * 獲取 分數
     */
    public List<Score> getScores() {
        return this.scores;
    }

    /**
     * 設置 分數
     */
    public void setScores(List<Score> scores) {
        this.scores = scores;
    }
}

對象B:

package com.test;

import com.wordnik.swagger.annotations.ApiModel;
import com.wordnik.swagger.annotations.ApiModelProperty;

import java.io.Serializable;

/**
 * test-manager
 * Created by xian.juanjuan on 2017-5-11 16:25.
 */
@ApiModel(description = "test-manager   Created by xian.juanjuan on 2017-5-11 16:25.")
public class Score implements Serializable {

    private static final long serialVersionUID = -6345327076401038020L;
    /**
     * 分數
     */
    @ApiModelProperty(value = "分數")
    private String subject;

    /**
     * 科目
     */
    @ApiModelProperty(value = "科目")
    private double score;

    /**
     * 學生信息
     */
    @ApiModelProperty(value = "學生信息")
    private Student student;

    /**
     * 獲取 分數
     */
    public String getSubject() {
        return this.subject;
    }

    /**
     * 設置 分數
     */
    public void setSubject(String subject) {
        this.subject = subject;
    }

    /**
     * 獲取 科目
     */
    public double getScore() {
        return this.score;
    }

    /**
     * 設置 科目
     */
    public void setScore(double score) {
        this.score = score;
    }

    /**
     * 獲取 學生信息
     */
    public Student getStudent() {
        return this.student;
    }

    /**
     * 設置 學生信息
     */
    public void setStudent(Student student) {
        this.student = student;
    }
}

測試

package com.test;

import com.alibaba.fastjson.JSONObject;

import java.util.ArrayList;
import java.util.List;

/**
 * test-manager
 * Created by xian.juanjuan on 2017-5-11 16:25.
 */
public class Test {

    public static void main(String[] args){

        Student student = new Student();
        student.setUserId("001");
        student.setUserName("小神經");

        Score score = new Score();
        score.setSubject("語文");
        score.setScore(100);
        score.setStudent(student);
        // TODO score入庫

        List<Score> scores = new ArrayList<>();
        scores.add(score);

        student.setScores(scores);
        //TODO student入庫

        System.out.print("運行完畢,學生信息爲:"+ JSONObject.toJSONString(student));
    }
}

運行結果:

"C:\Program Files\Java\jdk1.8.0_71\bin\java" -Didea.launcher.port=7532 "-Didea.launcher.bin.path=D:\soft\IntelliJ IDEA 2016.1.1\bin" -classpath C:\Users\xian.juanjuan\AppData\Local\Temp\classpath92.jar -Dfile.encoding=UTF-8 com.intellij.rt.execution.application.AppMain com.jyall.goods.product.service.Test
運行完畢,學生信息爲:{"scores":[{"score":100,"student":{"$ref":"$"},"subject":"語文"}],"userId":"001","userName":"小神經"}
Process finished with exit code 0

debug看運行過程中的參數信息:


score和student之間出現循環賦值,如果這裏的對象屬性比較多的時候,這種循環調用之後會導致該線程的堆棧異常,最終導致StackOverflowError異常;如何避免這種情況發生呢?可以克隆或者新建對象:

例如:

package com.jyall.goods.product.service;

import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.BeanUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * goods-main-manager
 * Created by xian.juanjuan on 2017-5-11 16:25.
 */
public class Test {

    public static void main(String[] args){

        Student student = new Student();
        student.setUserId("001");
        student.setUserName("小神經");

        Score score = new Score();
        score.setSubject("語文");
        score.setScore(100);
        //避免循環調用出現StackOverflowError異常,這裏用臨時對象studentTemp
        Student studentTemp = new Student();
        BeanUtils.copyProperties(student,studentTemp);
        score.setStudent(studentTemp);
        // TODO score入庫

        List<Score> scores = new ArrayList<>();
        scores.add(score);

        student.setScores(scores);
        //TODO student入庫

        System.out.print("運行完畢,學生信息爲:"+ JSONObject.toJSONString(student));
    }
}
互相嵌套過程中不會出現死循環現象~


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章