一般栈溢出是因为在某个class A中调用了class A.所以就陷入了死循环.
问题的基本原理如下:
Class A{
public A(){
a= new A();
}
}
你说这能不造成java.lang.StackOverflowError嘛,所以写代码我们要避免写这样的代码,应该将其放入到 方法体中(自己的Constructer除外) 或者是放入到 Static 中,以上的代码用JVM的指令,其实如下:
0: aload_0
1: invokespecial #1; //Method java/lang/object .<init>
4: aload_0
5: new #2; //class A
8: dup
9: invokespecial #3; //Method java/lang/object .<init>
12: putfield #4; //Field a:LA;
15: return
在这里 constructer 中是调用 init , 而 static 是调用 cinit , 固我们如果将自己的对象放入到 static 中是不会找成循环的, 而如果将自己本身放到 constructer 中他就会不段的调用 init , 所以才发生了上面的java.lang.StackOverflowError 溢出错误.
当然,一般人不会犯这么低级的错误.
下面我就拿我的项目遇到的问题来说一下.
我的问题是由于在某个类中与另一个类有一对多关系.导致陷入了死循环.
代码如下:
一对多类:User.java(一个User对应多个letter)
public class User {
private List<Letter> lettersForFromId;
private List<Letter> lettersForToId;
public User() {}
@OneToMany(fetch = FetchType.LAZY, mappedBy = "userByFromId")
public List<Letter> getLettersForFromId() {
return this.lettersForFromId;
}
public void setLettersForFromId(List<Letter> lettersForFromId) {
this.lettersForFromId = lettersForFromId;
}
@OneToMany(fetch = FetchType.LAZY, mappedBy = "userByToId")
public List<Letter> getLettersForToId() {
return this.lettersForToId;
}
public void setLettersForToId(List<Letter> lettersForToId) {
this.lettersForToId = lettersForToId;
}
}
多对一类:Letter.java
public class Letter extends IdEntity {
private static final long serialVersionUID = -2305610965537901463L;
private User userByToId;
private User userByFromId;
public Letter() {
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "to_id", nullable = false)
public User getUserByToId() {
return this.userByToId;
}
public void setUserByToId(User userByToId) {
this.userByToId = userByToId;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "from_id", nullable = false)
public User getUserByFromId() {
return this.userByFromId;
}
public void setUserByFromId(User userByFromId) {
this.userByFromId = userByFromId;
}
看到上面例子,仔细对比一下,不难发现. 导致我的User与Letter无限递归,导致陷入死循环,导致栈溢出.
解决方法:
在Letter中所有调用User处加上@JsonIgnore,如:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "to_id", nullable = false)
@JsonIgnore
public User getUserByToId() {
return this.userByToId;
}
@JsonIgnore的意思是不再向下便利.
到此,问题解决了.
这里主要是记录一下学习笔记,希望能顺便帮助一下遇到相同问题的朋友.
具体问题还是要具体分析.