8

We are running on Windows 7 Enterprise, SP1, 64bit. We just installed Java 7 on all our machines, which causes the following problem:

When my program tries to communicate with the OpenTestArchitecture-API from Quality Center it fails to create the ActiveX-Component. I use JACOB as my Java-COM library. Upgrading to the latest version of JACOB does not change anything.

The following test works with jdk1.6.0_24 (32 bit) but fails with jdk1.7.0_04 (32 bit):

import java.io.File;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.LibraryLoader;

public class JacobTest {
    static {
        File lib = new File("lib/" + LibraryLoader.getPreferredDLLName() + ".dll");
        System.setProperty(LibraryLoader.JACOB_DLL_PATH, lib.getAbsolutePath());

        System.out.println("JACOB_DLL_PATH = " + lib.getAbsolutePath());
        LibraryLoader.loadJacobLibrary();
    }

    public static void main(String[] args) {
        try {
            // Excel: Works with jdk1.6.0_24 AND jdk1.7.0_04
            System.out.println("new ActiveXComponent(\"Excel.Application\");");
            new ActiveXComponent("Excel.Application");

            // Quality Center OTAClient: Only works with jdk1.6.0_24
            System.out.println("ActiveXComponent component = new ActiveXComponent(\"TDApiOle80.TDConnection\");");
            ActiveXComponent component = new ActiveXComponent("TDApiOle80.TDConnection");

            System.out.println("ComThread.InitSTA();");
            ComThread.InitSTA();

            System.out.println("Dispatch.call(component, \"InitConnectionEx\", \"http://intranet/qcbin\");");
            Dispatch.call(component, "InitConnectionEx", "http://intranet/qcbin");
        }
        catch (Exception exception) {
            exception.printStackTrace();
        }
    }
}

jdk1.6.0_24 output:

JACOB_DLL_PATH = C:\Development\Java\Test\JacobTest\lib\jacob-1.17-M2-x86.dll

new ActiveXComponent("Excel.Application");
ActiveXComponent component = new ActiveXComponent("TDApiOle80.TDConnection");
ComThread.InitSTA();
Dispatch.call(component, "InitConnectionEx", "http://intranet/qcbin");

jdk1.7.0_04 output:

JACOB_DLL_PATH = C:\Development\Java\Test\JacobTest\lib\jacob-1.17-M2-x86.dll

new ActiveXComponent("Excel.Application");
ActiveXComponent component = new ActiveXComponent("TDApiOle80.TDConnection");
com.jacob.com.ComFailException: Invalid access to memory location.
    at com.jacob.com.Dispatch.createInstanceNative(Native Method)
    at com.jacob.com.Dispatch.<init>(Dispatch.java:99)
    at com.jacob.activeX.ActiveXComponent.<init>(ActiveXComponent.java:58)
    at JacobTest.main(JacobTest.java:26)

The original ComFailException-Message is "Can't co-create object" but I've edited the following Code in the jacob Dispatch.cpp: (I didn't touch CoCreateInstance, I just wanted to know what the HRESULT was)

  // standard creation
  hr = CoCreateInstance(clsid,NULL,CLSCTX_LOCAL_SERVER|CLSCTX_INPROC_SERVER,IID_IUnknown, (void **)&punk);
  if (!SUCCEEDED(hr)) {
     if (hr == REGDB_E_CLASSNOTREG)
        ThrowComFail(env, "Can't co-create object: REGDB_E_CLASSNOTREG", hr);
     if (hr == CLASS_E_NOAGGREGATION)
        ThrowComFail(env, "Can't co-create object: CLASS_E_NOAGGREGATION", hr);
     if (hr == E_NOINTERFACE)
        ThrowComFail(env, "Can't co-create object: E_NOINTERFACE", hr);
     if (hr == E_POINTER)
        ThrowComFail(env, "Can't co-create object: E_POINTER", hr);

     _com_error error(hr);
     LPCTSTR errorText = error.ErrorMessage();

     ThrowComFail(env, errorText, hr);
     return;
  }

Does anyone have a clue what the problem could be? The only difference is that I switch between the Java 6 and Java 7 runtime.

Thanks very much for your help!

PS: Excel works with both versions and a switch to the com4j-Library does not change anything. (I have a com4j-Test, but I didn't post it because I've already posted enough code)

Edit: The same test works with Windows XP, SP3 and Java 7.

oliver31
  • 2,523
  • 3
  • 19
  • 25
  • 1
    It's not clear whether the exception you are getting from original jacob code is a "memory access violation" or an HRESULT ? – Alex Shnayder May 13 '12 at 09:26
  • And if you can clarify whether same behavior reproduces using com4j and java 7. – Alex Shnayder May 13 '12 at 09:27
  • The original Jacob-Exception is "Can't co-create object". Because this does not tell very much I tried to figure out what the result of the CoCreateInstance function in the Native-Part was. The error-message from this method is "Invalid access to memory location". When I use com4j instead of Jacob i get the same results: "Excel.Application" and "TDApiOle80.TDConnection" works with Java 6, with Java 7 "Excel.Application" works but "TDApiOle80.TDConnection" does not. – oliver31 May 15 '12 at 06:49
  • Shouldn't the COM threading model (`ComThread.InitSTA()`) be set before creating the component that may require a particular one? – cynic May 15 '12 at 10:33
  • @cynic: Don't know. It works like it is with java 6. Calling ComThread.InitSTA() before creating the ActiveXComponent does not change the behavior with java 7. I just tried it. – oliver31 May 16 '12 at 11:26
  • Is it possible it comes from an "assembly" stuff ? For instance Java 6 runs with some version of DLLs but Java 7 runs with other versions... And finally the OTAClient.dll is not linked with expected DLL versions. – Yves Martin May 16 '12 at 11:35
  • InitSTA should be applied before any operations, including creation of TDConnection, else in most cases it does fail with abscure errors like access violation. But if this has checked and did not help we are in bad luck. – Alex Shnayder May 19 '12 at 13:15
  • You should try to debug with debugger configured to stop on memory access violation and see where the exception originates. If it originates inside OTAClient.dll or inside Webclient.dll then most likely it's an edge case bug exposed by java 7. In which case you need to open a support ticket with QC support. – Alex Shnayder May 19 '12 at 13:35

1 Answers1

2

Jacob DLL is linked with jvm.dll (methods and structures) from the JRE. So my guess is that the Jacob DLL should be compiled from sources with Java 7 to load properly into Java 7 JRE.

You are not alone but I guess too few people are already running Java 7...

Update: I propose you investigate first with Process Monitor if there are some library or system calls failing in your Java process, before running the process itself in a debugger... Maybe OpenJDK 7 may be an option to try too, it should be easier to debug then, at least to diagnose what the problem is.

Yves Martin
  • 10,217
  • 2
  • 38
  • 77
  • I've already built jacob with java 7, but that did not change anything... Anyway, thanks for your answer! – oliver31 May 16 '12 at 11:22