I'm working with JNI and trying to unload (destroy) the VM using DestoryJavaVM function (I first call DetachCurrentThread method). It seems like the it has now influence on the VM and it is still up after the call. I read in old Sun posts that DestoryJavaVM had problems in the past (JDK1.1-1.3 in 2001) but I'm using JRE 6 and it probably should work now, right?
I need to Load\Unload a VM in the same living process since each loading requires another classes to load. Any ideas how it can be done?
Additional info:
At the unloading phase I can successfully detachCurrentThread and destroyVM (both return JNI_OK). I even FreeLibray (jvm.dll) successfuly (return 1).
When I try to Load the JVM again I can LoadLibrary(), then find the CreateVM function in the DLL and the call to CreateVM fails (return -1). What I'm doing wrong here?
Thanks,
Guy
Although it wouldn't answer your question on DestroyJavaVM.
OSGi comes to my mind you could put all classes in a bundle activate it run code and deactivate it, later you use another bundle. See Apache Felix.
Another option less elegant would be to exit the vm and restart it with another classpath.
You might check for errant threads. The Invocation API: Unloading the VM mentions, "The VM waits until the current thread is the only non-daemon user thread before it actually unloads." This is required by the Java Language Specification, 12.8.
DestroyJavaVM() doesn't support VM unloading.
DestroyJavaVM
Unloads a Java VM and reclaims its resources.
Any thread, whether attached or not, can invoke this function. If the current thread is attached, the VM waits until the current thread is the only non-daemon user-level Java thread. If the current thread is not attached, the VM attaches the current thread and then waits until the current thread is the only non-daemon user-level thread.
[...]
Unloading of the VM is not supported.
The documentation can seem a bit conflicting at first. What you can do is destroy your VM without problems, but since it doesn't unload properly you can never reload it again in the same process.
For any newbies visiting this question, refer Calling JNI_CreateJavaVM function twice
Short answer: You CANNOT create more than one JVM in a single process (this is by design).
Related
I have an existing project that uses Specflow and SpecRun to run some tests against Sauce Labs. I have a BeforeSenario hook that creates a RemoteWebDriver and an AfterScenario hook that closes this down.
I've now moved this into another project (copied the files over, just changed the namespace) and the first test runs fine but then get the following error:
An exception of type 'OpenQA.Selenium.WebDriverException' occurred in WebDriver.dll but was not handled in user code
Additional information: Unexpected error. The command you just sent (POST element) has no session ID.
This is generally caused by testing frameworks trying to run commands after the conclusion of a test.
For example, you may be trying to capture a screenshot or retrieve server logs
after selenium.stop() or driver.quit() was called in a tearDown method.
Please make sure this process happens before the session is ended.
I've compared the project and it's using the same version of SpecFlow, same .Net version. I can't see any difference between the two projects.
In my steps I have the following line:
public static IWebDriver driver = (IWebDriver)ScenarioContext.Current["driver"];
which I think is the issue as instead of getting a new instance of it from the ScenarioContext it's using the previous test's version which has now been disposed.
But I can't see why this is working in another project instead?
I am using the Specflow example in Github here
UPDATE
Looks like I've found the issue. In the Default.srprofile the testThreadCount was 1 whereas the value in the working solution was 10. I've now updated this to match and it works.
Not sure what this value should be though. I assume it shouldn't be the same number of tests, but then how do I get around my original issue of the shared driver context?
TestThreadCount specifics the number of threads used by SpecFlow+Runner (aka SpecRun) to execute the tests.
Each of the threads are separated. The default is AppDomain isolation, so every thread runs in a separate AppDomain.
In the SauceLab example there are 7 scenarios and the runner is configured to use 10 threads. This means, every scenario is executed in a different thread with its own AppDomain. As no thread executes a second scenario, you get this error not in the example
With only one thread, your thread is executing more than one scenario and you get this issue.
Easiest fix would be, if you remove the static from the field. For every scenario you get a new instance of the binding class. You do not have to remember it static.
For a better example how to use Selenium with SpecFlow & SpecFlow+ have a look here: https://github.com/techtalk/SpecFlow.Plus.Examples/tree/master/SeleniumWebTest
You have to adjust the WebDriver- class for using SauceLabs over the RemoteWebDriver.
Can We initialize Win sock in DLL_DETACH ? actulay i want to send some data when a process get terminated(DLL_DETACH)
DLL_DETACH is actually DLL_PROCESS_DETACH.
It is possible (i don't think that's any mechanism to prevent it) but it's not recommended.
WSAStartup lies in ws2_32.dll. Here's a fragment from DllMain official doc (Remarks section):
Calling functions that require DLLs other than Kernel32.dll may result in problems that are difficult to diagnose. For example, calling User, Shell, and COM functions can cause access violation errors, because some functions load other system components. Conversely, calling functions such as these during termination can cause access violation errors because the corresponding component may already have been unloaded or uninitialized.
Also, from WSAStartup official doc (same Remarks section):
The WSAStartup function typically leads to protocol-specific helper DLLs being loaded. As a result, the WSAStartup function should not be called from the DllMain function in a application DLL. This can potentially cause deadlocks. For more information, please see the DLL Main Function.
As an alternative sending the data (including the overhead of initializing the socket engine, creating the connection, and uninitializing the socket engine) could be achieved at the end of main (WinMain).
Calling WSAStartup() in DllMain() will result in a deadlock due to the loader lock. WSAStartup() can result in DLLs being loaded.
A better solution would be to install a service that can do the sending for. Talk to the service from DllMain() using your preferred interprocess comms method (shared memory, named pipes, etc).
I am developing a client-server software in which server is developed by python. I want to call a group of methods from a java program in python. All the java methods exists in one jar file. It means I do not need to load different jars.
For this purpose, I used jpype. For each request from client, I invoke a function of python which looks like this:
def test(self, userName, password):
Classpath = "/home/DataSource/DMP.jar"
jpype.startJVM(
"/usr/local/java/jdk1.7.0_60/jre/lib/amd64/server/libjvm.so",
"-ea",
"- Xmx512m",
"-Djava.class.path=%s" % Classpath)
NCh = jpype.JClass("Common.NChainInterface")
n = NCh(self._DB_ipAddress, self._DB_Port, self._XML_SCHEMA_PATH, self._DSTDir)
jpype.shutdownJVM()
For one function it works, but for the second call it cannot start jvm.
I saw a lot of complain about it but I could not find any solution for that. I appreciate it if any body can help.
If jpype has problem in multiple starting jvm, is there any way to start and stop jvm once? The server is deployed on a Ubuntu virtual machine but I do not have enough knowledge to write for example, a script for this purpose. Could you please provide a link, or an example?
Check isJVMStarted() before startJVM().
If JVM is running, it will return True, otherwise False.
def init_jvm(jvmpath=None):
if jpype.isJVMStarted():
return
jpype.startJVM(jpype.getDefaultJVMPath())
For a real example, see here.
I have solved it by adding these lines when defining the connection:
if not jpype.isJVMStarted():
jpype.startJVM(jvmPath, args)
This issue is not resolved by et9's answer above.
The problem is explained here.
Effectively you need to start/stop the JVM at the server/module level.
I have had success with multiple calls using this method in unit tests.
I am trying to have Eclipse perform a concrete action on shutdown (halt an external system that would need to be switched off manually otherwise). I understand there is an extension allowing to activate a plugin on startup ( org.eclipse.ui.IStartup ), but haven't found one to do so when closing Eclipse. Does such an extension even exist? If it doesn't, is there a way to have a script executed or to run some code when closing Eclipse?
Thank you.
The simplest answer is to add some code to the stop() method of your plugin. On a normal shutdown, then this method will be called at some point during the shutdown process.
One caveat, though. On abnormal shutdowns, the stop methods of bundles are not called. This will happen, for example, when someone presses CTRL-C from on the command line, or Force Quits from the task manager. I don't think there will be any easy way around this part, though.
For normal shutdowns, adding code to stop should be sufficient.
Does anyone have any ideas of how a DLL function can be made to wait for “input”, and how to call a specific instance of a DLL export?
I’m trying to convert a Windows service to a DLL. It contains a function that logs some boot-up information and then waits until told to quit. The logging functionality is worked out, but I need to figure out two issues.
After it performs its main functions, the export needs to sit there and wait (like the classic Press any key to continue…, but minus the interface)
I need a way of having an executable subsequently tell the paused instance that it’s time to exit
For the first problem, I considered going into a loop and waiting on some sort of trigger, but of course it should not go into a 100%-CPU cycle, so maybe WaitForSingleObject or perhaps waiting for a message (eg WM_APP).
For the second, I thought of some kind of inter-process communication, but hopefully not something as messy as shared-memory or semaphores (I used shared-mem, semaphores, signals, etc. in Unix in uni, but this is on Windows). Of course I need a way of accessing the specific instance of the called export.
You can use CreateEvent, SetEvent, and WaitForSingleObject. If the dll was loaded by the executable that needs to signal the event that is all that is required. If it is from separate executables it is only slightly more complicated. When you call CreateEvent, create a named Event. This named event can be accessed by multiple processes. If it needs to work across different users logged in, prefix the name with "Global\" and it will be the same event for all processes for all users.
//in dll
HANDLE eventHandle = CreateEvent( NULL, TRUE, FALSE, "Global\\My-Unique-Trigger-Event" );
//do stuff
WaitForSingleObject( eventHandle, INFINITE);
//exit
//in executable
HANDLE eventHandle = CreateEvent( NULL, TRUE, FALSE, "Global\\My-Unique-Trigger-Event" );
SetEvent( eventHandle );