#89 Dispatch references not being released

1.15
closed-invalid
nobody
Jacob COM (35)
5
2014-09-01
2010-03-23
No

Windows XP SP2
JACOB 1.14 and 1.15-M3
Java 1.6.0_13

This issue is related to the problem of looping through Microsoft Project TimeScaleValue objects. It seems that there is a limit on the number of references you can have to TimeScaleValue objects (see http://www.tech-archive.net/Archive/Office/microsoft.public.office.developer.com.add_ins/2006-04/msg00076.html\).

I tried calling dispatch.safeRelease without success. The 11th time through the loop I get

com.jacob.com.ComFailException: Invoke of: Value
Source:
Description: An unexpected error occurred with the method.

at com.jacob.com.Dispatch.invokev(Native Method)
at com.jacob.com.Dispatch.invokev(Dispatch.java:858)
at com.jacob.com.Dispatch.get(Dispatch.java:1258)

I then added a printf to the Dispatch.release JNI method that would print the reference counter after the disp->Release call. Here is sample output:

Mon Jan 11 00:00:00 CST 2010 value is 658.7826086956522
Counter for 798860 is 1
Mon Jan 18 00:00:00 CST 2010 value is 823.4782608695652
Counter for 799468 is 1
Mon Jan 25 00:00:00 CST 2010 value is 823.4782608695652
Counter for 800076 is 1
Mon Feb 01 00:00:00 CST 2010 value is 1303.4782608695652
Counter for 801316 is 1
Mon Feb 08 00:00:00 CST 2010 value is 1783.4782608695652
Counter for 801924 is 1

As I understand it the counter should be hitting 0 which causes the reference to be actually freed up.

I also tried the following Excel sample code:

ComThread.InitSTA();
ActiveXComponent xl = new ActiveXComponent("Excel.Application");
try {
Dispatch workbooks = xl.getProperty("Workbooks").toDispatch();
System.out.println("Releasing...");
workbooks.safeRelease();
System.out.println("Released...");
} catch (Exception e) {
e.printStackTrace();
} finally {
xl.invoke("Quit", new Variant[] {});
System.out.println("Calling ComThread.Release");
ComThread.Release();
}

with the following results:

Releasing...
Counter for 794740 is 1
Released...
Calling ComThread.Release
Counter for 793948 is 0

It appears that calling safeRelease on workbooks is not causing the reference counter to hit 0.

When looking at the JNI code, I noticed that Variant.toVariantDispatch calls AddRef. I commented out the call to AddRef as a test. This changed the output for the Excel sample code:

Releasing...
Counter for 794740 is 0
Released...
Calling ComThread.Release
Counter for 793948 is 0

and the output for the project loop:

Mon Jan 11 00:00:00 CST 2010 value is 658.7826086956522
Counter for 798852 is 0
Mon Jan 18 00:00:00 CST 2010 value is 823.4782608695652
Counter for 798852 is 0
Mon Jan 25 00:00:00 CST 2010 value is 823.4782608695652
Counter for 798852 is 0
Mon Feb 01 00:00:00 CST 2010 value is 1303.4782608695652
Counter for 798852 is 0
Mon Feb 08 00:00:00 CST 2010 value is 1783.4782608695652
Counter for 798852 is 0

I am also able to loop through all the TimeScaleValue objects without the COMFailException. Unfortunately the JVM now crashes with EXCEPTION_ACCESS_VIOLATION during ComThread.Release. The crash report files have included the following two stack traces for the identical code:

======================== Stack Trace 1 =================================

Stack: [0x003b0000,0x00400000], sp=0x003ffa88, free space=318k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C 0x0002049b
C [jacob-1.15-M3-x86.dll+0x302b0]
j com.jacob.com.Variant.release()V+0
j com.jacob.com.Variant.safeRelease()V+20
j com.jacob.com.ROT.clearObjects()V+197
j com.jacob.com.ComThread.Release()V+11
j JacobBug.main([Ljava/lang/String;)V+212
v ~StubRoutines::call_stub

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j com.jacob.com.Variant.release()V+0
j com.jacob.com.Variant.safeRelease()V+20
j com.jacob.com.ROT.clearObjects()V+197
j com.jacob.com.ComThread.Release()V+11
j JacobBug.main([Ljava/lang/String;)V+212
v ~StubRoutines::call_stub

======================== Stack Trace 2 =================================

Stack: [0x003b0000,0x00400000], sp=0x003fe69a, free space=313k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C 0x000a026f

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j com.jacob.com.Dispatch.release()V+0
j com.jacob.com.Dispatch.safeRelease()V+12
j com.jacob.com.ROT.clearObjects()V+197
j com.jacob.com.ComThread.Release()V+11
j JacobBug.main([Ljava/lang/String;)V+212
v ~StubRoutines::call_stub

Discussion

  • serkan

    serkan - 2010-03-23

    I've been hitting a similar problem as well try adding the following to beginnig of your program

    System.setProperty("com.jacob.autogc", "true");

     
  • Jason Kirchhoff

    Jason Kirchhoff - 2010-06-05

    The Excel code above had to change to:

    ComThread.InitSTA();
    ActiveXComponent xl = new ActiveXComponent("Excel.Application");
    try {
    Variant variant = xl.getProperty("Workbooks");
    Dispatch workbooks = variant.toDispatch();
    System.out.println("Releasing variant...");
    variant.safeRelease();
    System.out.println("Releasing dispatch...");
    workbooks.safeRelease();
    System.out.println("Released...");
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    xl.invoke("Quit", new Variant[] {});
    System.out.println("Calling ComThread.Release");
    ComThread.Release();
    }

    The important change is that after calling Variant.toDispatch, Variant.safeRelease is called. Variant.safeRelease ends up calling VariantClear (http://msdn.microsoft.com/en-us/library/aa909093.aspx). The documentation for VariantClear indicates "If the vt member is VT_DISPATCH, the object is released." This resolved the issue with the limit on the number of references you can have to Microsoft Project TimeScaleValue objects.

    For this situation you cannot enable garbage collection (com.jacob.autogc) and rely on the garbage collector to cleanup the variants in time.

     
  • Jason Kirchhoff

    Jason Kirchhoff - 2010-06-05
    • status: open --> closed-invalid
     

Log in to post a comment.