/// <summary> /// Create the Java VM and wrap it. /// </summary> /// <param name="jvmDllPath">(Optional) Path to jvm.dll where we'll load the JNI library. If not provided we'll try to infer its location from the Java install path.</param> /// <param name="attemptVmReuse"> /// This is an annoying workaround to a fundamental JNI problem: you can't host a JVM within the process again once you've hosted it once /// (ever, even if you destroy the first one). So if this flag is <c>true</c>, we'll attempt to find an existing JVM in the process and use that /// if available, and we won't destroy the JVM on dispose so subsequent constructions of this object will succeed. /// The downside of reuse of course is that if we're reusing it then we won't be able to construct it with fresh arguments. /// </param> internal JniWrapper(string jvmDllPath, bool attemptVmReuse, IEnumerable <JavaOption> options) { _currentThreadEnv = new ThreadLocal <IntPtr>(() => { IntPtr ret; unsafe { if (_vm.GetDelegate <GetEnv>()(_vmP, (IntPtr)(&ret), _jniVersion) == -2) { _vm.GetDelegate <AttachCurrentThread>()(_vmP, (IntPtr)(&ret), IntPtr.Zero); } return(ret); } }); if (String.IsNullOrEmpty(jvmDllPath)) { string javaHome = GetJavaInstallationPath(); _vmDll = Path.Combine(javaHome, "bin", "server", "jvm.dll"); } else { _vmDll = jvmDllPath; } if (!File.Exists(_vmDll)) { throw new InvalidOperationException("Couldn't find the runtime library for Java at: " + _vmDll); } IntPtr envP; IntPtr vmP; _vmDllModule = LoadLibrary(_vmDll); if (_vmDllModule == IntPtr.Zero) { throw new Win32Exception(); } if (attemptVmReuse) { _vmReuse = true; int numVms; unsafe { ThrowOnBadResult(GetDelegateFromJni <GetCreatedJavaVMs>("JNI_GetCreatedJavaVMs")(&vmP, 1, out numVms), "GetCreatedJavaVMs"); if (numVms >= 1) { _vmP = vmP; _vm = (JavaVM)Marshal.PtrToStructure(vmP, typeof(JavaVM)); ThrowOnBadResult(_vm.GetDelegate <AttachCurrentThread>()(_vmP, (IntPtr)(&envP), IntPtr.Zero), "AttachCurrentThread"); _envP = envP; _env = (JniEnv)Marshal.PtrToStructure(envP, typeof(JniEnv)); return; } } } JavaVMInitArgs vmArgs = new JavaVMInitArgs(); GetDelegateFromJni <GetDefaultJavaVMInitArgs>("JNI_GetDefaultJavaVMInitArgs")(ref vmArgs); vmArgs.Version = _jniVersion; vmArgs._nOptions = options.Count(); vmArgs._options = Marshal.AllocHGlobal(vmArgs._nOptions * Marshal.SizeOf(typeof(JavaVMOption))); IntPtr vmArgsP = Marshal.AllocHGlobal(Marshal.SizeOf(vmArgs)); try { int optionsLocation = 0; foreach (JavaOption currentOption in options) { Marshal.StructureToPtr(currentOption.ActualOption, vmArgs._options + optionsLocation * Marshal.SizeOf(typeof(JavaVMOption)), false); optionsLocation++; } Marshal.StructureToPtr(vmArgs, vmArgsP, false); unsafe { ThrowOnBadResult(GetDelegateFromJni <CreateJavaVM>("JNI_CreateJavaVM")(&vmP, &envP, vmArgsP), "CreateJavaVM"); _vm = (JavaVM)Marshal.PtrToStructure(vmP, typeof(JavaVM)); _env = (JniEnv)Marshal.PtrToStructure(envP, typeof(JniEnv)); _envP = envP; _vmP = vmP; } } finally { Marshal.DestroyStructure(vmArgsP, typeof(JavaVMInitArgs)); Marshal.FreeHGlobal(vmArgsP); Marshal.FreeHGlobal(vmArgs._options); } }