Need help with JNI inside of a COM DLL
I am writing a COM DLL and need some help. :-)
A.exe is calling by means of COM B.dll (which is my COM dll).
As a result, B.dll gets loaded into memory by Windows OS.
B.dll uses JNI to create a Java VM.
No problem so far.
As a result of A's call, now:
B.dll uses the VM to run the actual implementation written in Java.
B.dll returns from the COM method's implementation.
Again, no problem so far.
But now A.exe decides to release B, as a result, B.dll gets unloaded from memory.
A few seconds later, A.exe creates another instance of a COM object, so B.dll gets loaded again!
Now the problem starts...: Since there was a JavaVM created using JNI inside of this process already, I NEITHER can create a new one, NOR can I destroy the old one and create anew one, NOR can I attach to the old one. In fact, I tried all three options:
* Create a second VM --> Is not supported by JDK 1.6!
* Destroy the old one, create a new one --> Is not supported by JDK 1.6 (or is possibly a bug of the JDK)!
* Attach to the old one --> Works only in 50% of the cases, in all other cases Windows' "Data Execution Protection" shuts down A.exe when calling AttachToCurrentThread!
In fact, I cannot beliefe that it is impossible to write COM in-process servers using JNI.
What is my fault?
I know that there is an ActiveX bridge in the JDK, so in fact it MUST be possible to solve this using JNI, too (because I assume the AX bridge uses JNI internally).
Thank you for all tips that you can give me! :-)
# 1
> * Create a second VM --> Is not supported by JDK 1.6!
> * Destroy the old one, create a new one --> Is not
> supported by JDK 1.6 (or is possibly a bug of the
> JDK)!
Neither of those has ever been possible in any Sun VM.
> * Attach to the old one --> Works only in 50% of the
> cases, in all other cases Windows' "Data Execution
> Protection" shuts down A.exe when calling
> AttachToCurrentThread!
>
That doesn't necessarily mean that the problem exists in the VM. C/C++ memory errors can cause bizarre behavior far from the location of the error.
These days I wouldn't use JNI unless I absolutely could not use a separate application. Usage then has one app running the java one and using some mechanism for communcation. It makes it much easier to debug this way.
> In fact, I cannot beliefe that it is impossible to
> write COM in-process servers using JNI.
>
I know that I gave up trying to access COM and trying to successfully destroy the COM interface in JNI. Using a separate app made it all work and as I suggested much easier to debug.
# 2
> > * Create a second VM --> Is not supported by JDK
> 1.6!
> > * Destroy the old one, create a new one --> Is not
> > supported by JDK 1.6 (or is possibly a bug of the
> > JDK)!
> Neither of those has ever been possible in any Sun
> VM.
Seems to be sad but true. In fact I do not understand why it is not supported because it would make things so much easier. Also it is strange that destroy is not supported, since there even is an explanation in the docs how it works internally and there is no annotation that destroy is not supported while such an annotation is found at other JNI methods. Is the doc inconsistent?
> > * Attach to the old one --> Works only in 50% of
> the
> > cases, in all other cases Windows' "Data Execution
> > Protection" shuts down A.exe when calling
> > AttachToCurrentThread!
> That doesn't necessarily mean that the problem exists
> in the VM. C/C++ memory errors can cause bizarre
> behavior far from the location of the error.
But the C++ code is error free -- it works perfectly as soon as I do not add that few JNI lines. Also the JNI code is error free -- I did copy & paste into a standalone exe and it works very well there.
> These days I wouldn't use JNI unless I absolutely
> could not use a separate application. Usage then has
> one app running the java one and using some mechanism
> for communcation. It makes it much easier to debug
> this way.
But that makes programming more complex and very slow. I mean, what technology are you using to communicate between COM and JVM? I want to have the fastest possible communication and I think JNI is suited best. Also this is the "JNI forum" and not the "Don't use JNI Forum". :-)
> > In fact, I cannot beliefe that it is impossible to
> > write COM in-process servers using JNI.
> I know that I gave up trying to access COM and trying
> to successfully destroy the COM interface in JNI.
> Using a separate app made it all work and as I
> suggested much easier to debug.
Actuall it must be possible to do what I want because the ActiveX bridge included in the SDK does the same: It is an in-process COM server (DLL) written in C, that presumably uses JNI to run Java code. But I did not find the source of that on the web, even now in the Open Source Java days. :-(
Thanks a lot for your ideas!
Markus
# 3
>
> But that makes programming more complex and very
> slow. I mean, what technology are you using to
> communicate between COM and JVM? I want to have the
> fastest possible communication and I think JNI is
> suited best. Also this is the "JNI forum" and not the
> "Don't use JNI Forum". :-)
Slow is relative. JNI itself is slow that it why even fundamental classes like String do not use it.
On box communication using sockets is very fast. However, the communcation methodology can also depend on what the app is doing.
And again separate apps are much easier to debug and maintain. Have you actually profiled different apps or do you have specific performance requirements that drive this?
>
> > > In fact, I cannot beliefe that it is impossible to
> > > write COM in-process servers using JNI.
> > I know that I gave up trying to access COM and trying
> > to successfully destroy the COM interface in JNI.
> > Using a separate app made it all work and as I
> > suggested much easier to debug.
>
> Actuall it must be possible to do what I want because
> the ActiveX bridge included in the SDK does the same:
> It is an in-process COM server (DLL) written in C,
> that presumably uses JNI to run Java code. But I did
> not find the source of that on the web, even now in
> the Open Source Java days. :-(
And you know that it works in all possible situations?
In my case the de-init of the com interface would intermittently throw a system level exception of some sort which even with system capture methods could not be captured. Thus the VM exited. And that wasn't acceptable in a J2EE server. I don't know that I would necessarily attribute this to JNI at all.
