StackOverflowError异常处理

来源:互联网 发布:照片大小修剪软件 编辑:程序博客网 时间:2024/06/08 15:27

 在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));    }}
互相嵌套过程中不会出现死循环现象~


2 0