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

Posted starrow

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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引擎已经代劳。


以上是关于42. Lotus Notes中的垃圾回收之Java的主要内容,如果未能解决你的问题,请参考以下文章

如何为 Lotus Notes 编写和使用 Java 代理

lotus notes8.5软件出现问题!!!

Lotus Notes 富文本中的 AX 2009 附件

在 Lotus Notes 中使用 XML URL 作为视图

Java 到 Lotus Notes 的连接问题

如何在 Lotus Notes 中创建一个按钮以查看收件箱中的最新电子邮件?