Mysterious arbitrary crash when using COM and JNI

A

aetdata

I have an application in Java accessing a VC++ dll for getting the text
in a Internet Explorer Server component. I access the dll frequently
once each second to get the latest content. It usually works fine and
does what I want but sooner or later it crashes the program completely.
I have tried to isolate the crash but can not find exactly what is
going wrong. I also use some try..catch blocks and test all return
values, but nothing seem to help. I am getting quite desperate by now
so any help would be greatly appreciated!

Code as follows, I call the
Java_poker_jni_ipoker_IPTHandler_getOutput() method once each second
from the Java side, when it crashes I get the message "Exception
thrown 1", but nothing else...

JNIEXPORT jstring JNICALL
Java_poker_jni_ipoker_IPTHandler_getOutput(JNIEnv *env, jobject obj){

try {

LPTSTR str;

//init COM/OLE
if(CoInitialize( NULL ) != S_OK)
MsgBoxA("COM NOT INITED OK!");
else{
str = getText();
}

if(str == NULL){
MsgBoxA("STR = NULL");
str = "";
}else if(str == ""){
MsgBoxA("STR = ''");
}else if(!str){
MsgBoxA("NOT STR");
}

jstring res = env->NewStringUTF(str);

CoUninitialize();

//delete str;

return res;

} catch(...) {
LPTSTR str = "";
MsgBoxA("Exception thrown 1");
jstring res = env->NewStringUTF(str);
CoUninitialize();
return res;
}
}

LPTSTR getText(){

try {

CComPtr<IHTMLDocument2> spDoc;
CComPtr<IHTMLElement> pHTMLElement;

CComBSTR bstrText;
LPTSTR str = "";

HRESULT hr;

hr = GetHTMLDocument( chatWindow, spDoc );

if ( SUCCEEDED(hr) ){


hr = spDoc->get_body(&pHTMLElement);

if ( SUCCEEDED(hr) ){

hr = pHTMLElement->get_innerText(&bstrText);

if( SUCCEEDED(hr) ){
str =(char *)_bstr_t(bstrText);
}

}

}

//clean up
pHTMLElement.Release();
spDoc.Release();

return str;

} catch(...) {
MsgBoxA("Exception thrown 2");
}

return "";
}


HRESULT GetHTMLDocument( HWND hwnd, CComPtr<IHTMLDocument2> &spDoc )
{

try{

TCHAR lpszClass[512];
HRESULT hr;


if ( ::GetClassName(hwnd,
lpszClass,(sizeof(lpszClass)/sizeof(TCHAR))-1) == 0 ){
return E_INVALIDARG;
}

if ( _tcscmp(lpszClass, _T("Internet Explorer_Server")) == 0 ){


LRESULT lRes;


::SendMessageTimeout( hwnd, nMsgGetHTML, 0L, 0L,
SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes );

if ( pfObjectFromLresult != NULL ) {

hr = (*pfObjectFromLresult)( lRes, IID_IHTMLDocument2,
0, (void**)&spDoc );
CHECK_HR( hr );

}


}
else
{
hr = E_INVALIDARG;
}

//delete[] lpszClass;

return hr;

} catch(...) {
MsgBoxA("Exception thrown 3");
}

return E_INVALIDARG;
}
 
C

Chris Uppal

I have an application in Java accessing a VC++ dll for getting the text
in a Internet Explorer Server component. I access the dll frequently
once each second to get the latest content. It usually works fine and
does what I want but sooner or later it crashes the program completely.
I have tried to isolate the crash but can not find exactly what is
going wrong.

I can't suggest anything definite, but a few things that might be worth
checking:

if(CoInitialize( NULL ) != S_OK)

I'm not sure if doing thousands of CoInitialize()/CoUninitialize() pairs is how
COM is supposed to be used. I'd be suspicious of that. You could try writing
a simple, /single-threaded/, C++ that repeatedly executes your JNI code (or a
close equivalent), sleeping for a second each time around the loop. If that
fails too, then at least you have narrowed down the problem and can forget
about JNI/COM interactions.

And then try it in a multi-threaded test harness unless you are sure that your
code (as seen by COM) is always running on the same single OS thread.

} catch(...) {
LPTSTR str = "";
MsgBoxA("Exception thrown 1");
jstring res = env->NewStringUTF(str);

It would be a good idea to try to say /what/ the error was here. A message box
that identifies /where/ it was caught isn't much use when you are using a
generic catch block.


Erratically occurring bugs are often due to one of two things.

One is that you have a rogue pointer somewhere (a bug in your C++ code, or even
in the COM object's code if it is inproc). There are tools for looking for
such things, some as simple as a debugging malloc() implementation (such as
that provided with VC if you use a debugging build), others very complicated
commercial tools that heavily instrument your application (sorry, I can't
remember any names).

Another is that you have a threading problem. You don't mention what use you
make of threads, but it's worth considering. JNI and COM are both designed to
"know" about threads, and both have very definite rules about what you can do,
when you can do it, and what thread you can do it on. Since many Java
applications do use threads (e.g. all Swing/AWT apps do) you have to consider
how your JNI code is working in a threaded environment (which may well be
trivially correct) /and/ how that further interacts with what COM expects. A
specific warning is that you are using COM in a DLL, which is well-known to be
tricky to get right, and AFAIK usually requires an additional separate worker
thread to issue COM calls from. I know very little about COM, though, so I may
be wrong. I suggest Google (or your search engine of choice) for threads, COM,
and DLL for more info.

There are extant COM<->Java bridges available. I think there's one (I don't
know how usable it is) in Eclipse. There are at least two commercial bridges.
You might find it convenient to use such a tool instead of rolling-your-own.
Or looking at the source might give you ideas for fixing your own bridge code.

-- chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top