42. Lotus Notes中的垃圾回收之Java

Java里有垃圾回收的物事(issue),Lotus Notes中的Java当然也有。垃圾回收在Java语言里有专门论述,对Lotus Notes里的Java程序都是适用的。只不过Lotus Notes中的Java程序与一般所说的Java程序相比,有些特殊,其垃圾回收也有值得说明之处。

Lotus Notes中的Java程序,可以分为两类。一是传统客户端或Web应用中,用Java写的代理。这几乎是传统Lotus Notes程序能够使用Java的唯一场合(如果排除Web Service则就是)。主要是为了利用Java与LotusScript相比更强大的功能和丰富的类库,往往用于开发与其他系统的接口。二是Xpages出现后,以Bean的形式开发业务逻辑。与使用服务器端JavaScript相比的好处,在22. 为什么要在XPages中写Java里已经详述。

这两类Java程序,特别是前者,的最大特点,就是主要围绕Domino对象展开。我们要说明的垃圾回收问题,也是针对这些Domino对象。Lotus Notes程序的核心就是操纵Notes数据库的各种对象,从数据库、视图、文档一直到域。这些功能是用C语言开发的,并且提供了C++的接口,使用这两种语言接口的开发包都可以从IBM网站上下载。我们大量使用的LotusScript,访问Domino对象,也是通过LSX绑定,调用本机代码。在32. LotusNotes中的垃圾回收之LotusScript一文里已经介绍了LotusScript中回收这些对象的特点。我们现在来看看Java。

Java里一般对象都是生存在称为堆的内存区域中,由虚拟机负责分配存储控件和自动回收。Domino对象的功能,不是用Java重新开发的(在经济、性能和可靠性上,都不占优势),而是使用JNI(Java NativeInterface即Java本机接口)调用相应的C++对象来实现。Java中的Database、View、Document这些对象,只是一些很浅的套子,负责将被调用的方法传递给后端的C++对象。Java中的垃圾回收仍然会销毁这些前端对象,但是C++对象就必须手动清除。这就是所有的Domino的Java类都有一个recycle()方法的原因。

和写C++代码一样,在对象不再被需要时,应该尽早地销毁它,也就是调用这个对象的recycle()方法。这些Domino对象有一个特点,某个对象被销毁时,由它所派生出的其他对象也会被自动销毁。所以当一个文档被销毁时,不需要再调用其中的域的recycle()方法;一个数据库对象被销毁时,其中的所有视图和文档对象都会被销毁;一个会话对象(Session)被销毁时,所有这个会话过程中创建的Domino对象都会被销毁。最后这种情况正是一个Java代理结束时发生的事情。读一读下面的一个Java代理的代码,你能预测在控制台会打印出那些消息吗?

import java.util.Date;
import lotus.domino.*;

public class JavaAgent extends AgentBase {

    public void NotesMain() {

      try {
          Session session = getSession();
          AgentContext agentContext = session.getAgentContext();
          // (Your code goes here)
          Logger.log("Print message from NotesMain()");
          Foo foo=new Foo();
          foo.showMe();
          StaticFoo.showMe();          
          
      } catch(Exception e) {
          e.printStackTrace();
       }
   }
    
    class Foo{
    	
    	public void showMe(){
    		Logger.log("I am a " + this.getClass().getName());
    	}
    	
    	protected void finalize() throws Throwable{
    		try {
    			Logger.log("Print message from finalize() in an object being garbage collected.");
    		} catch (Exception e) {
    			e.printStackTrace();			
    		}finally{
    			super.finalize();
    		}
    	}

    }
    
}
class Logger{
	public static void log(Object msg){
		System.out.println("[" + Logger.getCurrentTimeString() + "] " + msg);
		
	}
	
	public static String getCurrentTimeString(){
		return (new Date()).toString();
	}
}
class StaticFoo{
	public static void showMe(){
		Logger.log("Print message from a static method in StaticFoo.");
	}
	protected void finalize() throws Throwable{
		try {
			Logger.log("Print message from finalize() in a 'static' object being garbage collected.");
		} catch (Exception e) {
			e.printStackTrace();			
		}finally{
			super.finalize();
		}
	}
}
答案是:

[Thu Nov 28 15:07:06 CST 2013] Print message from NotesMain()
[Thu Nov 28 15:07:06 CST 2013] I am a JavaAgent$Foo
[Thu Nov 28 15:07:06 CST 2013] Print message from a static method in StaticFoo.
[Thu Nov 28 15:07:11 CST 2013] Print message from finalize() in an object being garbage collected.
前三行是代理运行时输出到控制台的消息,最后一行则是代理结束后过了几秒钟那个Foo对象被垃圾回收时输出的消息。至于只被调用了静态方法的StaticFoo类,finalize方法并没有运行,因为程序没有创建StaticFoo的实例。反过来看也很符合逻辑,如果StaticFoo类会经过某种垃圾回收过程,那么在其finalize方法里使用的Logger类也会,但是在垃圾回收过程中运行的finalize方法却可以正常使用它的静态方法,这就说明它和垃圾回收完全是无关的。与自定义的Foo类的实例一样,代理中用到的所有Domino对象也会被销毁,不过这要等到代理结束以后。
因为Domino对象垃圾回收的这个特点,在Java代理中,常见的遍历一个视图或者文档集合的循环里,我们需要比LotusScript更多的代码。下面的两段代码(其一取自Lotus Notes的帮助文档)展示了略微不同的两种风格,思路都在于使用两个文档对象,其中一个作为指针或临时对象:

//a.
      Document tmpdoc;
      Document doc = view.getFirstDocument();
      while (doc != null) {
        System.out.println("\t" + doc.getItemValueString("Subject"));
        tmpdoc = view.getNextDocument(doc);
        doc.recycle();
        doc = tmpdoc;
      }

//b.
	Document doc, pdoc;
	pdoc=view.getFirstDocument();
	while (pdoc!=null){
		doc=pdoc;
		//do something with doc
		pdoc=view.getNextDocument(doc);
		doc.recycle();
	}

至于Xpages中用到的Java,Xpages引擎已经省去我们费心,很频繁地(具体频率不得而知)自动回收Domino对象,以至于在Bean中对任意一个保存在字段内的Domino对象,不能够初始化一次以后就直接使用,而要在每次读取前初始化。这也可以理解,因为服务器端JavaScript就是由IBM的Java版本的JavaScript引擎来解释执行的。它引用各种Domino对象时,便从来不需要考虑回收,Xpages引擎已经代劳。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值