private void AttachToCurrentJVM(JavaVMInitArgs args) { // This is only required if you want to reuse the same instance of the JVM // This is especially useful if you are using JNI in a webservice. see page 89 of the // Java Native Interface: Programmer's Guide and Specification by Sheng Liang if (AttachToCurrentJVMThread) { int nVMs; IntPtr javaVirtualMachine; int res = JavaVM.JNI_GetCreatedJavaVMs(out javaVirtualMachine, 1, out nVMs); if (res != JNIReturnValue.JNI_OK) { throw new Exception("JNI_GetCreatedJavaVMs failed (" + res.ToString() + ")"); } if (nVMs > 0) { jvm = new JavaVM(javaVirtualMachine); res = jvm.AttachCurrentThread(out env, args); if (res != JNIReturnValue.JNI_OK) { throw new Exception("AttachCurrentThread failed (" + res.ToString() + ")"); } } } }
/// <summary> /// /// </summary> /// <param name="options"></param> /// <param name="AddToExistingJVM"></param> /// <param name="targetVersion">Specified the version</param> public void LoadVM(Dictionary <string, string> options, bool AddToExistingJVM = false, JNIVersion targetVersion = JNIVersion.JNI_VERSION_10) { // Set the directory to the location of the JVM.dll. // This will ensure that the API call JNI_CreateJavaVM will work // TODO : maybe remove this after changing DLLImport by Assembly dynamic loading // This probably break pathes to ressources // Directory.SetCurrentDirectory(Path.GetDirectoryName(JavaNativeInterface.__jvmDllPath)); var args = new JavaVMInitArgs(); args.version = (int)targetVersion; args.ignoreUnrecognized = JavaVM.BooleanToByte(true); // True if (options.Count > 0) { args.nOptions = options.Count; var opt = new JavaVMOption[options.Count]; int i = 0; foreach (KeyValuePair <string, string> kvp in options) { string optionString = kvp.Key.ToString() + "=" + kvp.Value.ToString(); opt[i++].optionString = Marshal.StringToHGlobalAnsi(optionString); } fixed(JavaVMOption *a = &opt[0]) { // prevents the garbage collector from relocating the opt variable as this is used in unmanaged code that the gc does not know about args.options = a; } } if (!AttachToCurrentJVMThread) { IntPtr environment; IntPtr javaVirtualMachine; int result = JavaVM.JNI_CreateJavaVM(out javaVirtualMachine, out environment, &args); if (result != JNIReturnValue.JNI_OK) { throw new Exception("Cannot create JVM " + result.ToString()); } jvm = new JavaVM(javaVirtualMachine); env = new JNIEnv(environment); } else { AttachToCurrentJVM(args); } }
protected virtual void Dispose(bool disposing) { // free native resources if there are any. foreach (KeyValuePair <string, IntPtr> javaClass in usedClasses) { if (javaClass.Value != IntPtr.Zero) { env.DeleteGlobalRef(javaClass.Value); usedClasses[javaClass.Key] = IntPtr.Zero; } } for (int i = 0, end = usedObject.Count; i < end; ++i) { IntPtr javaObject = usedObject[i]; if (javaObject != IntPtr.Zero) { env.DeleteLocalRef(javaObject); usedObject[i] = IntPtr.Zero; } } if (disposing) { // free managed resources if (jvm != null) { jvm.Dispose(); jvm = null; } if (env != null) { env.Dispose(); env = null; } } }
/// <summary> /// /// </summary> /// <param name="forcedJVMDllPath"></param> public JavaNativeInterface(string forcedJVMDllPath = "") { if (forcedJVMDllPath.Length > 0) { JavaNativeInterface.__jvmDllPath = forcedJVMDllPath; } else if (JavaNativeInterface.__jvmDllPath.Length == 0) { // Search for a java runtime near the current assembly string codeBase = Assembly.GetExecutingAssembly().CodeBase; UriBuilder uri = new UriBuilder(codeBase); string assemblyDir = Path.GetDirectoryName(Uri.UnescapeDataString(uri.Path)) + Path.DirectorySeparatorChar; string[] searchResult = Directory.GetFiles(assemblyDir, "jvm.dll", SearchOption.AllDirectories); if (searchResult.Length > 0) { JavaNativeInterface.__jvmDllPath = searchResult[0]; } else { string envJavaHome = Environment.GetEnvironmentVariable("JAVA_HOME"); if (envJavaHome.Length > 0) { searchResult = Directory.GetFiles(envJavaHome, "jvm.dll", SearchOption.AllDirectories); if (searchResult.Length > 0) { JavaNativeInterface.__jvmDllPath = searchResult[0]; } } else { foreach (string key in JavaNativeInterface.JAVA_REGISTRY_KEYS) { string javaVersion = (string)Registry.GetValue(key, "CurrentVersion", null); if (javaVersion == null) { continue; } else { JavaNativeInterface.__javaVersion = javaVersion; string javaKey = Path.Combine(key, javaVersion); string javaHomeKey = (string)Registry.GetValue(javaKey, "JavaHome", null); if (javaHomeKey == null) { continue; } else { searchResult = Directory.GetFiles(javaHomeKey, "jvm.dll", SearchOption.AllDirectories); if (searchResult.Length > 0) { JavaNativeInterface.__jvmDllPath = searchResult[0]; break; } else { continue; } } } } if (JavaNativeInterface.__jvmDllPath.Length == 0) // no runtime found in registry keys { throw new Exception("No Java runtime available to launch a JVM, please install java or contact your IT administrator."); } } } Console.WriteLine("Using " + JavaNativeInterface.__jvmDllPath); JavaVM.loadAssembly(JavaNativeInterface.__jvmDllPath); } }
private JValue[] ParseParameters(IntPtr javaClass, string sig, params object[] param) { JValue[] retval = new JValue[param.Length]; int startIndex = sig.IndexOf('(') + 1; for (int i = 0; i < param.Length; i++) { string paramSig = ""; if (sig.Substring(startIndex, 1) == "[") { paramSig = sig.Substring(startIndex++, 1); } if (sig.Substring(startIndex, 1) == "L") { paramSig = paramSig + sig.Substring(startIndex, sig.IndexOf(';', startIndex) - startIndex); startIndex++; // skip past ; } else { paramSig = paramSig + sig.Substring(startIndex, 1); } startIndex = startIndex + (paramSig.Length - (paramSig.IndexOf("[", StringComparison.Ordinal) + 1)); if (param[i] is string) { if (!paramSig.Equals("Ljava/lang/String")) { throw new Exception("Signature (" + paramSig + ") does not match parameter value (" + param[i].GetType().ToString() + ")."); } retval[i] = new JValue() { l = env.NewString(param[i].ToString(), param[i].ToString().Length) }; } else if (param[i] == null) { retval[i] = new JValue(); // Just leave as default value } else if (paramSig.StartsWith("[")) { retval[i] = ProcessArrayType(javaClass, paramSig, param[i]); } else { retval[i] = new JValue(); FieldInfo paramField = retval[i].GetType().GetFields(BindingFlags.Public | BindingFlags.Instance).AsQueryable().FirstOrDefault(a => a.Name.ToUpper().Equals(paramSig)); if ((paramField != null) && ((param[i].GetType() == paramField.FieldType) || ((paramField.FieldType == typeof(bool)) && (param[i] is byte)))) { paramField.SetValueDirect(__makeref(retval[i]), paramField.FieldType == typeof(bool) // this is an undocumented feature to set struct fields via reflection ? JavaVM.BooleanToByte((bool)param[i]) : param[i]); } else { throw new Exception("Signature (" + paramSig + ") does not match parameter value (" + param[i].GetType().ToString() + ")."); } } } return(retval); }