论坛首页 Java企业应用论坛

JBoss5.1下无状态Bean的抽筋现象及原因分析

浏览 3058 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (2) :: 隐藏帖 (5)
作者 正文
   发表时间:2010-06-27   最后修改:2010-06-27

最近在学习ejb,在JBoss5.1-jdk6.0版本下进行部署和测试,发现一个怪异的抽筋现象,闲话少说,看代码和运行结果:

1、先定义接口:

public interface StatelessEjb {
	public void compute(int i);
	public int getResult();
}

2、定义ejb

@Stateless
@Remote
public class StatelessEjbBean implements StatelessEjb {
	private int state;

	public void compute(int i) {
		state += i;
		System.out.println("compute():state="+state);
	}

	public int getResult() {
		System.out.println("getResult():state="+state);
		return state;
	}

}

 3、定义测试的客户端

public class StatelessEjbClient {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws NamingException {
		InitialContext ic = new InitialContext();
		
		//第一次会话
		StatelessEjb ejb = (StatelessEjb) ic.lookup("StatelessEjbBean/remote");
		System.out.println(ejb.getResult());
		ejb.compute(1);
		System.out.println(ejb.getResult());
		ejb.compute(1);
		System.out.println(ejb.getResult());
		ejb.compute(1);
		System.out.println(ejb.getResult());
		
		System.out.println("---------------------------------");
		
		//第二次会话
		StatelessEjb ejb2 = (StatelessEjb) ic.lookup("StatelessEjbBean/remote");
		System.out.println(ejb2.getResult());
		ejb2.compute(1);
		System.out.println(ejb2.getResult());
		ejb2.compute(1);
		System.out.println(ejb2.getResult());
		ejb2.compute(1);
		System.out.println(ejb2.getResult());
		
		System.out.println(ejb.equals(ejb2));
		System.out.println(ejb == ejb2);
	}

}

 在正确部署后运行客户端,抽筋现象出现,可能出现多种运行结果,下面给出典型的两种:

可能出现的运行结果1:

测试客户端的运行结果:

0
0
0
0
---------------------------------
0
0
0
0
true
false

 JBoss服务器端的输出结果:

18:14:48,390 INFO  [STDOUT] getResult():state=0
18:14:48,406 INFO  [STDOUT] compute():state=1
18:14:48,421 INFO  [STDOUT] getResult():state=0
18:14:48,421 INFO  [STDOUT] compute():state=2
18:14:48,437 INFO  [STDOUT] getResult():state=0
18:14:48,453 INFO  [STDOUT] compute():state=3
18:14:48,453 INFO  [STDOUT] getResult():state=0
18:14:48,718 INFO  [STDOUT] getResult():state=0
18:14:48,718 INFO  [STDOUT] compute():state=4
18:14:48,734 INFO  [STDOUT] getResult():state=0
18:14:48,750 INFO  [STDOUT] compute():state=5
18:14:48,765 INFO  [STDOUT] getResult():state=0
18:14:48,781 INFO  [STDOUT] compute():state=6
18:14:48,796 INFO  [STDOUT] getResult():state=0

 可能出现的运行结果2:

测试客户端的运行结果:

0
1
2
3
---------------------------------
3
4
5
6
true
false
 

 

JBoss服务器端的输出结果:

18:26:56,875 INFO  [STDOUT] getResult():state=0
18:26:56,906 INFO  [STDOUT] compute():state=1
18:26:56,921 INFO  [STDOUT] getResult():state=1
18:26:56,937 INFO  [STDOUT] compute():state=2
18:26:56,953 INFO  [STDOUT] getResult():state=2
18:26:56,968 INFO  [STDOUT] compute():state=3
18:26:56,984 INFO  [STDOUT] getResult():state=3
18:26:57,000 INFO  [STDOUT] getResult():state=3
18:26:57,015 INFO  [STDOUT] compute():state=4
18:26:57,031 INFO  [STDOUT] getResult():state=4
18:26:57,046 INFO  [STDOUT] compute():state=5
18:26:57,046 INFO  [STDOUT] getResult():state=5
18:26:57,062 INFO  [STDOUT] compute():state=6
18:26:57,078 INFO  [STDOUT] getResult():state=6

 

由于目前为止没有弄清楚原因,本人简单分析原因可能如下(可能分析有误,请多指教):

1、可能是JBoss的bug。这个是最能解释上面原因的,也可能是最不靠谱的。

2、针对第一种运行结果,是不是gerResult()在返回时直接取缓存,从而使结果是0.

 

欢迎大家给出正确的原因分析,谢谢!!

 

   发表时间:2010-06-27  
楼主理解错了无状态的EJB。无状态的EJB不应该保存对象的状态信息,比如这里的state,Stateless bean的状态是不确定的,不是JBoss的Bug。
0 请登录后投票
   发表时间:2010-06-28   最后修改:2010-06-28
mercyblitz 写道
楼主理解错了无状态的EJB。无状态的EJB不应该保存对象的状态信息,比如这里的state,Stateless bean的状态是不确定的,不是JBoss的Bug。


状态不确定可以理解,但jboss端的这段结果太异常了,理解不了(同一个变量竟然有不同的值):
  
18:14:48,390 INFO  [STDOUT] getResult():state=0
18:14:48,406 INFO  [STDOUT] compute():state=1
18:14:48,421 INFO  [STDOUT] getResult():state=0
18:14:48,421 INFO  [STDOUT] compute():state=2
18:14:48,437 INFO  [STDOUT] getResult():state=0
18:14:48,453 INFO  [STDOUT] compute():state=3
18:14:48,453 INFO  [STDOUT] getResult():state=0
18:14:48,718 INFO  [STDOUT] getResult():state=0
18:14:48,718 INFO  [STDOUT] compute():state=4
18:14:48,734 INFO  [STDOUT] getResult():state=0
18:14:48,750 INFO  [STDOUT] compute():state=5
18:14:48,765 INFO  [STDOUT] getResult():state=0
18:14:48,781 INFO  [STDOUT] compute():state=6
18:14:48,796 INFO  [STDOUT] getResult():state=0  

同一个类中的变量state,在两个方法中得到的值居然不一样?!
0 请登录后投票
   发表时间:2010-06-28  
一个无状态的SessionBean,你是不能假设两次调用的是服务器端的同一个对象的。这里有两个问题:
1. 你的ejb是客户端,跟服务器端的实现是无关的。
2. stateless session bean里面用类变量是标准的anti-pattern。你得到的结果只能说,这一次服务器端用了两个或以上的实例来响应你的调用,一个响应compute(),另外一个或多个响应getResult()。
0 请登录后投票
   发表时间:2011-04-04  
我对两次引用不相等表示不能理解,为什么呢?按照无状态会话Bean的特性,应该是在初始化的时候,容器已经创建无状态会话Bean对象,并且初始化成员属性,所有打印出state为0,很正常,但是容器一般情况下是不会再次创建另一个无状态会话Bean的,无状态会话Bean是存放在一个对象池里面的,当下一次再次需要的时候,容器会再次把已经创建的Bean对象交给客户端,但是当第二次引用的时候,为什么这两个引用不相等呢?

至于state一直在累加,我猜想会不会是创建了两个Bean实例呢?

我很菜,班门弄斧,希望大牛们指点一下,很不解啊?
0 请登录后投票
   发表时间:2011-04-05  
你又没指定单例,当然会产生多个无状态Bean。产生多少个实例受不同服务器实现和你的配置而不同。这种Bean有可能只产生1个,也可能产生很多,从对象池拿出的时候,你是无法确定到底是哪个的,只能说是一个空闲的Bean。
对这个Bean的内部属性,除了在初始化时候一样外,是不做任何保证的。因为这是无状态的。你如果要它返回的是你刚才累加的,那么应该使用有状态Bean。
0 请登录后投票
   发表时间:2011-04-05  
谢谢,猫咪,初学者多向你学习一下!
0 请登录后投票
   发表时间:2011-04-08   最后修改:2011-04-08
在服务器日志上把调用的类句柄打印出来看看就知道了。
另外有个问题,楼主在Stateless Bean里放个变量要作什么用呢?
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics