平时工作StackOverflowError是很少出现的,今天写一个demo出现了,记录一下,应该算是一个典型的StackOverflowError。
[DEBUG] 2018-08-08 14:52:19,159 method:org.springframework.beans.factory.xml.PluggableSchemaResolver.resolveEntity(PluggableSchemaResolver.java:119)
Found XML schema [http://www.springframework.org/schema/beans/spring-beans.xsd] in classpath: org/springframework/beans/factory/xml/spring-beans-4.3.xsd
[DEBUG] 2018-08-08 14:52:19,278 method:org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:92)
Loading bean definitions
[DEBUG] 2018-08-08 14:52:19,329 method:org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:224)
Loaded 5 bean definitions from location pattern [spring.xml]
[DEBUG] 2018-08-08 14:52:19,330 method:org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:617)
Bean factory for org.springframework.context.support.ClassPathXmlApplicationContext@32d2fa64: org.springframework.beans.factory.support.DefaultListableBeanFactory@1b2abca6: defining beans [stu,stu2,stu3,stu4,classes]; root of factory hierarchy
[DEBUG] 2018-08-08 14:52:19,507 method:org.springframework.context.support.AbstractApplicationContext.initMessageSource(AbstractApplicationContext.java:734)
Unable to locate MessageSource with name 'messageSource': using default [org.springframework.context.support.DelegatingMessageSource@5d0bf09b]
[DEBUG] 2018-08-08 14:52:19,548 method:org.springframework.context.support.AbstractApplicationContext.initApplicationEventMulticaster(AbstractApplicationContext.java:758)
Unable to locate ApplicationEventMulticaster with name 'applicationEventMulticaster': using default [org.springframework.context.event.SimpleApplicationEventMulticaster@6bbe85a8]
[DEBUG] 2018-08-08 14:52:19,551 method:org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:730)
Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1b2abca6: defining beans [stu,stu2,stu3,stu4,classes]; root of factory hierarchy
[DEBUG] 2018-08-08 14:52:19,613 method:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:221)
Creating shared instance of singleton bean 'stu'
[DEBUG] 2018-08-08 14:52:19,614 method:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:449)
Creating instance of bean 'stu'
[DEBUG] 2018-08-08 14:52:19,688 method:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
Eagerly caching bean 'stu' to allow for resolving potential circular references
[DEBUG] 2018-08-08 14:52:19,900 method:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:221)
Creating shared instance of singleton bean 'classes'
[DEBUG] 2018-08-08 14:52:19,900 method:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:449)
Creating instance of bean 'classes'
[DEBUG] 2018-08-08 14:52:19,901 method:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
Eagerly caching bean 'classes' to allow for resolving potential circular references
[DEBUG] 2018-08-08 14:52:19,910 method:org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:247)
Returning eagerly cached instance of singleton bean 'stu' that is not fully initialized yet - a consequence of a circular reference
[DEBUG] 2018-08-08 14:52:19,911 method:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:221)
Creating shared instance of singleton bean 'stu2'
[DEBUG] 2018-08-08 14:52:19,911 method:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:449)
Creating instance of bean 'stu2'
[DEBUG] 2018-08-08 14:52:19,911 method:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
Eagerly caching bean 'stu2' to allow for resolving potential circular references
[DEBUG] 2018-08-08 14:52:19,916 method:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:485)
Finished creating instance of bean 'stu2'
[DEBUG] 2018-08-08 14:52:19,960 method:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:485)
Finished creating instance of bean 'classes'
[DEBUG] 2018-08-08 14:52:19,960 method:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:485)
Finished creating instance of bean 'stu'
[DEBUG] 2018-08-08 14:52:19,961 method:org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:251)
Returning cached instance of singleton bean 'stu2'
[DEBUG] 2018-08-08 14:52:19,961 method:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:221)
Creating shared instance of singleton bean 'stu3'
[DEBUG] 2018-08-08 14:52:19,962 method:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:449)
Creating instance of bean 'stu3'
[DEBUG] 2018-08-08 14:52:20,014 method:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
Eagerly caching bean 'stu3' to allow for resolving potential circular references
[DEBUG] 2018-08-08 14:52:20,015 method:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:485)
Finished creating instance of bean 'stu3'
[DEBUG] 2018-08-08 14:52:20,016 method:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:221)
Creating shared instance of singleton bean 'stu4'
[DEBUG] 2018-08-08 14:52:20,017 method:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:449)
Creating instance of bean 'stu4'
[DEBUG] 2018-08-08 14:52:20,019 method:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
Eagerly caching bean 'stu4' to allow for resolving potential circular references
[DEBUG] 2018-08-08 14:52:20,020 method:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:485)
Finished creating instance of bean 'stu4'
[DEBUG] 2018-08-08 14:52:20,022 method:org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:251)
Returning cached instance of singleton bean 'classes'
[DEBUG] 2018-08-08 14:52:20,028 method:org.springframework.context.support.AbstractApplicationContext.initLifecycleProcessor(AbstractApplicationContext.java:785)
Unable to locate LifecycleProcessor with name 'lifecycleProcessor': using default [org.springframework.context.support.DefaultLifecycleProcessor@63eef88a]
[DEBUG] 2018-08-08 14:52:20,030 method:org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:251)
Returning cached instance of singleton bean 'lifecycleProcessor'
[DEBUG] 2018-08-08 14:52:20,044 method:org.springframework.core.env.PropertySourcesPropertyResolver.getProperty(PropertySourcesPropertyResolver.java:92)
Could not find key 'spring.liveBeansView.mbeanDomain' in any property source
[DEBUG] 2018-08-08 14:52:20,047 method:org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:251)
Returning cached instance of singleton bean 'classes'
Exception in thread "main" java.lang.StackOverflowError
at java.lang.StringBuilder.append(StringBuilder.java:136)
at com.jiangcheng.entity.Student.toString(Student.java:15)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at java.lang.String.valueOf(String.java:2994)
...
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
Disconnected from the target VM, address: '127.0.0.1:55210', transport: 'socket'
Process finished with exit code 1
从日志可以看出这次StackOverflowError是由于相互调用无限循环造成的,代码如下:
spring.xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--配置student对象-->
<!--<bean id="stu" class="com.jiangcheng.entity.Student"></bean>--><!--v1 打印之后没有初始化值-->
<bean id="stu" class="com.jiangcheng.entity.Student">
<property name="id" value="1"></property>
<property name="name">
<value><![CDATA[<张三>]]></value>
</property>
<property name="age" value="23"></property>
<!-- 将classes对象赋给stu对象 -->
<property name="classes" ref="classes"></property>
</bean>
<bean id="stu2" class="com.jiangcheng.entity.Student">
<property name="id" value="1"></property>
<property name="name" value="李四"></property>
<property name="age" value="23"></property>
</bean>
<!-- 通过有参构造函数创建对象 -->
<bean id="stu3" class="com.jiangcheng.entity.Student">
<constructor-arg name="id" value="3"></constructor-arg>
<constructor-arg name="name" value="小明"></constructor-arg>
<constructor-arg name="age" value="22"></constructor-arg>
</bean>
<bean id="stu4" class="com.jiangcheng.entity.Student">
<constructor-arg index="0" value="4"></constructor-arg>
<constructor-arg index="1" value="小明"></constructor-arg>
<constructor-arg index="2" value="22"></constructor-arg>
</bean>
<!--创建classes对象-->
<bean id="classes" class="com.jiangcheng.entity.Classes">
<property name="id" value="1"></property>
<property name="name" value="Java"></property>
<property name="students">
<!-- 注入student对象 -->
<list>
<ref bean="stu2"/>
<ref bean="stu3"/>
</list>
</property>
</bean>
</beans>
Student.java
package com.jiangcheng.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 类名称:Student<br>
* 类描述:<br>
* 创建时间:2018年08月08日<br>
*
* @author jiangcheng
* @version 1.0.0
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
private int id;
private String name;
private int age;
private Classes classes;
public Student(int id,String name,int age){
this.id = id;
this.name = name;
this.age = age;
}
}
Classes.java
package com.jiangcheng.entity;
import lombok.Data;
import java.util.List;
/**
* 类名称:Classes<br>
* 类描述:<br>
* 创建时间:2018年08月08日<br>
*
* @author jiangcheng
* @version 1.0.0
*/
@Data
public class Classes {
private int id;
private String name;
private List<Student> students;
}
StudentTest.java
package com.jiangcheng.entity;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import static org.junit.Assert.*;
/**
* 类名称:StudentTest<br>
* 类描述:<br>
* 创建时间:2018年08月08日<br>
*
* @author jiangcheng
* @version 1.0.0
*/
public class StudentTest {
public static void main(String[] args) {
//Student student = new Student();
//System.out.println(student);
//1.加载spring.xml配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
//2.通过id获取值对象
//Student stu = applicationContext.getBean(Student.class);//No qualifying bean of type 'com.jiangcheng.entity.Student' available: expected single matching bean but found 2: stu,stu2
//Student stu = (Student) applicationContext.getBean("stu");///Student(id=1, name=<张三>, age=23)
//Student stu = (Student) applicationContext.getBean("stu3");///Student(id=1, name=<张三>, age=23)
//Student stu = (Student) applicationContext.getBean("stu4");///Student(id=1, name=<张三>, age=23)
Classes classes = (Classes) applicationContext.getBean("classes");
System.out.println(classes);
}
}
解决方案,修改依赖关系,spring.xml中对classes对象的ref进行稍稍改变,去掉stu引用
<!--创建classes对象-->
<bean id="classes" class="com.jiangcheng.entity.Classes">
<property name="id" value="1"></property>
<property name="name" value="Java"></property>
<property name="students">
<!-- 注入student对象 -->
<list>
<ref bean="stu2"/>
<ref bean="stu3"/>
</list>
</property>
</bean>
再次运行test,打印日志
Classes(id=1, name=Java, students=[Student(id=1, name=李四, age=23, classes=null), Student(id=3, name=小明, age=22, classes=null)])