You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by pt...@apache.org on 2017/11/14 14:18:06 UTC
[2/3] ignite git commit: IGNITE-5343 .NET: Work with JNI directly,
get rid of C++ layer
http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/AppDomains.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/AppDomains.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/AppDomains.cs
new file mode 100644
index 0000000..4b87df5
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/AppDomains.cs
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+ using System.Diagnostics;
+ using System.Runtime.InteropServices;
+ using Apache.Ignite.Core.Common;
+
+ /// <summary>
+ /// AppDomain accessor.
+ /// <para />
+ /// Logic is borrowed from internal .NET Framework classes.
+ /// See System.Deployment.Application.NativeMethods.
+ /// </summary>
+ internal static class AppDomains
+ {
+ // ReSharper disable InconsistentNaming
+ // ReSharper disable UnusedMember.Global
+ /** */
+ private static Guid CLSID_CLRMetaHost = new Guid(
+ 0x9280188d, 0xe8e, 0x4867, 0xb3, 0xc, 0x7f, 0xa8, 0x38, 0x84, 0xe8, 0xde);
+
+ /** */
+ private static Guid IID_CLRMetaHost = new Guid(
+ 0xD332DB9E, 0xB9B3, 0x4125, 0x82, 0x07, 0xA1, 0x48, 0x84, 0xF5, 0x32, 0x16);
+
+ /** */
+ private static Guid IID_CLRRuntimeInfo = new Guid(
+ 0xBD39D1D2, 0xBA2F, 0x486a, 0x89, 0xB0, 0xB4, 0xB0, 0xCB, 0x46, 0x68, 0x91);
+
+ /** */
+ private static Guid CLSID_CorRuntimeHost = new Guid(
+ 0xcb2f6723, 0xab3a, 0x11d2, 0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e);
+
+ /** */
+ private static Guid IID_CorRuntimeHost = new Guid(
+ 0xcb2f6722, 0xab3a, 0x11d2, 0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e);
+
+ /// <summary>
+ /// Gets the default application domain.
+ /// </summary>
+ public static _AppDomain GetDefaultAppDomain()
+ {
+ object objHost;
+ int hr = NativeMethods.CLRCreateInstance(ref CLSID_CLRMetaHost, ref IID_CLRMetaHost, out objHost);
+
+ if (hr < 0)
+ {
+ throw new IgniteException("Failed to get default AppDomain. Cannot create meta host: " + hr);
+ }
+
+ var host = (ICLRMetaHost) objHost;
+ var vers = Environment.Version;
+ var versString = string.Format("v{0}.{1}.{2}", vers.Major, vers.Minor, vers.Build);
+ var runtime = (ICLRRuntimeInfo) host.GetRuntime(versString, ref IID_CLRRuntimeInfo);
+
+ bool started;
+ uint flags;
+ runtime.IsStarted(out started, out flags);
+ Debug.Assert(started);
+
+ var rtHost = (ICorRuntimeHost) runtime.GetInterface(ref CLSID_CorRuntimeHost, ref IID_CorRuntimeHost);
+
+ _AppDomain domain;
+ rtHost.GetDefaultDomain(out domain);
+
+ return domain;
+ }
+
+ [ComImport, Guid("D332DB9E-B9B3-4125-8207-A14884F53216"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ private interface ICLRMetaHost
+ {
+ [return: MarshalAs(UnmanagedType.Interface)]
+ object GetRuntime(string version, ref Guid iid);
+ }
+
+ [ComImport, Guid("BD39D1D2-BA2F-486a-89B0-B4B0CB466891"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ private interface ICLRRuntimeInfo
+ {
+ void GetVersionString(char[] buffer, int bufferLength);
+ void GetRuntimeDirectory(char[] buffer, int bufferLength);
+ bool IsLoaded(IntPtr hProcess);
+ void LoadErrorString(uint id, char[] buffer, int bufferLength, int lcid);
+ void LoadLibrary(string path, out IntPtr hMdodule);
+ void GetProcAddress(string name, out IntPtr addr);
+ [return: MarshalAs(UnmanagedType.Interface)]
+ object GetInterface(ref Guid clsid, ref Guid iid);
+ bool IsLoadable();
+ void SetDefaultStartupFlags(uint flags, string configFile);
+ void GetDefaultStartupFlags(out uint flags, char[] configFile, int configFileLength);
+ void BindAsLegacyV2Runtime();
+ void IsStarted(out bool started, out uint flags);
+ }
+
+ [ComImport, Guid("CB2F6722-AB3A-11d2-9C40-00C04FA30A3E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ private interface ICorRuntimeHost
+ {
+ void CreateLogicalThreadState();
+ void DeleteLogicalThreadState();
+ void SwitchinLogicalThreadState(IntPtr cookie);
+ void SwitchoutLogicalThreadState(out IntPtr cookie);
+ void LocksHeldByLogicalThread(out int count);
+ void MapFile(IntPtr hFile, out IntPtr address);
+ void GetConfiguration(out IntPtr config);
+ void Start();
+ void Stop();
+ void CreateDomain(string name, object identity, out _AppDomain domain);
+ void GetDefaultDomain(out _AppDomain domain);
+ }
+
+ private static class NativeMethods
+ {
+ [DllImport("mscoree.dll")]
+ public static extern int CLRCreateInstance(ref Guid clsid, ref Guid iid,
+ [MarshalAs(UnmanagedType.Interface)] out object ptr);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/CallbackDelegates.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/CallbackDelegates.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/CallbackDelegates.cs
new file mode 100644
index 0000000..4eb1d29
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/CallbackDelegates.cs
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+ using System.Runtime.InteropServices;
+ using System.Security;
+
+ /// <summary>
+ /// Java -> .NET callback delegates.
+ /// <para />
+ /// Delegates are registered once per JVM.
+ /// Every callback has igniteId argument to identify related Ignite instance
+ /// (this value is passed as EnvPtr to PlatformIgnition.start).
+ /// </summary>
+ [SuppressUnmanagedCodeSecurity]
+ internal static class CallbackDelegates
+ {
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ public delegate void LoggerLog(IntPtr env, IntPtr clazz, long igniteId, int level, IntPtr message,
+ IntPtr category, IntPtr error, long memPtr);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ public delegate bool LoggerIsLevelEnabled(IntPtr env, IntPtr clazz, long ignteId, int level);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ public delegate void ConsoleWrite(IntPtr env, IntPtr clazz, IntPtr message, bool isError);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ public delegate long InLongOutLong(IntPtr env, IntPtr clazz, long igniteId, int op, long arg);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ public delegate long InLongLongLongObjectOutLong(IntPtr env, IntPtr clazz,
+ long igniteId, int op, long arg1, long arg2, long arg3, IntPtr arg);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Callbacks.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Callbacks.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Callbacks.cs
new file mode 100644
index 0000000..1e2989f
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Callbacks.cs
@@ -0,0 +1,292 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+ using System.Collections.Concurrent;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Linq;
+ using System.Runtime.InteropServices;
+ using System.Threading;
+ using Apache.Ignite.Core.Impl.Handle;
+ using Apache.Ignite.Core.Log;
+
+ /// <summary>
+ /// Java -> .NET callback dispatcher.
+ /// Instance of this class should only exist once per process, in the default AppDomain.
+ /// </summary>
+ internal sealed class Callbacks : MarshalByRefObject
+ {
+ /** Holds delegates so that GC does not collect them. */
+ // ReSharper disable once CollectionNeverQueried.Local
+ private readonly List<Delegate> _delegates = new List<Delegate>();
+
+ /** Holds Ignite instance-specific callbacks. */
+ private readonly HandleRegistry _callbackRegistry = new HandleRegistry(100);
+
+ /** Console writers. */
+ private readonly ConcurrentDictionary<long, ConsoleWriter> _consoleWriters
+ = new ConcurrentDictionary<long, ConsoleWriter>();
+
+ /** Gets the JVM. */
+ private readonly Jvm _jvm;
+
+ /** Console writer id generator. */
+ private long _consoleWriterId;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Callbacks"/> class.
+ /// </summary>
+ public Callbacks(Env env, Jvm jvm)
+ {
+ Debug.Assert(env != null);
+ Debug.Assert(jvm != null);
+
+ _jvm = jvm;
+ RegisterNatives(env);
+ }
+
+ /** <inheritdoc /> */
+ public override object InitializeLifetimeService()
+ {
+ // Ensure that cross-AppDomain reference lives forever.
+ return null;
+ }
+
+ /// <summary>
+ /// Registers callback handlers.
+ /// </summary>
+ public long RegisterHandlers(UnmanagedCallbacks cbs)
+ {
+ Debug.Assert(cbs != null);
+
+ return _callbackRegistry.AllocateCritical(cbs);
+ }
+
+ /// <summary>
+ /// Releases callback handlers.
+ /// </summary>
+ public void ReleaseHandlers(long igniteId)
+ {
+ _callbackRegistry.Release(igniteId);
+ }
+
+ /// <summary>
+ /// Registers the console writer.
+ /// </summary>
+ public long RegisterConsoleWriter(ConsoleWriter writer)
+ {
+ Debug.Assert(writer != null);
+
+ var id = Interlocked.Increment(ref _consoleWriterId);
+
+ var res = _consoleWriters.TryAdd(id, writer);
+ Debug.Assert(res);
+
+ return id;
+ }
+
+ /// <summary>
+ /// Registers the console writer.
+ /// </summary>
+ public void ReleaseConsoleWriter(long id)
+ {
+ ConsoleWriter writer;
+ var res = _consoleWriters.TryRemove(id, out writer);
+ Debug.Assert(res);
+ }
+
+ /// <summary>
+ /// Registers native callbacks.
+ /// </summary>
+ private void RegisterNatives(Env env)
+ {
+ // Native callbacks are per-jvm.
+ // Every callback (except ConsoleWrite) includes envPtr (third arg) to identify Ignite instance.
+
+ using (var callbackUtils = env.FindClass(
+ "org/apache/ignite/internal/processors/platform/callback/PlatformCallbackUtils"))
+ {
+ // Any signature works, but wrong one will cause segfault eventually.
+ var methods = new[]
+ {
+ GetNativeMethod("loggerLog", "(JILjava/lang/String;Ljava/lang/String;Ljava/lang/String;J)V",
+ (CallbackDelegates.LoggerLog) LoggerLog),
+
+ GetNativeMethod("loggerIsLevelEnabled", "(JI)Z",
+ (CallbackDelegates.LoggerIsLevelEnabled) LoggerIsLevelEnabled),
+
+ GetNativeMethod("consoleWrite", "(Ljava/lang/String;Z)V",
+ (CallbackDelegates.ConsoleWrite) ConsoleWrite),
+
+ GetNativeMethod("inLongOutLong", "(JIJ)J", (CallbackDelegates.InLongOutLong) InLongOutLong),
+
+ GetNativeMethod("inLongLongLongObjectOutLong", "(JIJJJLjava/lang/Object;)J",
+ (CallbackDelegates.InLongLongLongObjectOutLong) InLongLongLongObjectOutLong)
+ };
+
+ try
+ {
+ env.RegisterNatives(callbackUtils, methods);
+ }
+ finally
+ {
+ foreach (var nativeMethod in methods)
+ {
+ Marshal.FreeHGlobal(nativeMethod.Name);
+ Marshal.FreeHGlobal(nativeMethod.Signature);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the native method.
+ /// </summary>
+ private unsafe NativeMethod GetNativeMethod(string name, string sig, Delegate d)
+ {
+ _delegates.Add(d);
+
+ return new NativeMethod
+ {
+ Name = (IntPtr)IgniteUtils.StringToUtf8Unmanaged(name),
+ Signature = (IntPtr)IgniteUtils.StringToUtf8Unmanaged(sig),
+ FuncPtr = Marshal.GetFunctionPointerForDelegate(d)
+ };
+ }
+
+ /// <summary>
+ /// <see cref="ILogger.Log"/> callback.
+ /// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+ private void LoggerLog(IntPtr envPtr, IntPtr clazz, long igniteId, int level, IntPtr message, IntPtr category,
+ IntPtr errorInfo, long memPtr)
+ {
+ try
+ {
+ var cbs = _callbackRegistry.Get<UnmanagedCallbacks>(igniteId, true);
+ var env = _jvm.AttachCurrentThread();
+
+ var message0 = env.JStringToString(message);
+ var category0 = env.JStringToString(category);
+ var errorInfo0 = env.JStringToString(errorInfo);
+
+ cbs.LoggerLog(level, message0, category0, errorInfo0, memPtr);
+ }
+ catch (Exception e)
+ {
+ _jvm.AttachCurrentThread().ThrowToJava(e);
+ }
+ }
+
+ /// <summary>
+ /// <see cref="ILogger.IsEnabled"/> callback.
+ /// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+ private bool LoggerIsLevelEnabled(IntPtr env, IntPtr clazz, long igniteId, int level)
+ {
+ try
+ {
+ var cbs = _callbackRegistry.Get<UnmanagedCallbacks>(igniteId, true);
+
+ return cbs.LoggerIsLevelEnabled(level);
+ }
+ catch (Exception e)
+ {
+ _jvm.AttachCurrentThread().ThrowToJava(e);
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// 3 longs + object -> long.
+ /// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+ private long InLongLongLongObjectOutLong(IntPtr env, IntPtr clazz, long igniteId,
+ int op, long arg1, long arg2, long arg3, IntPtr arg)
+ {
+ try
+ {
+ var cbs = _callbackRegistry.Get<UnmanagedCallbacks>(igniteId, true);
+
+ return cbs.InLongLongLongObjectOutLong(op, arg1, arg2, arg3, arg);
+ }
+ catch (Exception e)
+ {
+ _jvm.AttachCurrentThread().ThrowToJava(e);
+ return 0;
+ }
+ }
+
+ /// <summary>
+ /// long -> long.
+ /// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+ private long InLongOutLong(IntPtr env, IntPtr clazz, long igniteId,
+ int op, long arg)
+ {
+ try
+ {
+ var cbs = _callbackRegistry.Get<UnmanagedCallbacks>(igniteId, true);
+
+ return cbs.InLongOutLong(op, arg);
+ }
+ catch (Exception e)
+ {
+ _jvm.AttachCurrentThread().ThrowToJava(e);
+
+ return 0;
+ }
+ }
+
+ /// <summary>
+ /// System.out.println -> Console.Write.
+ /// <para />
+ /// Java uses system output which can not be accessed with native .NET APIs.
+ /// For example, unit test runners won't show Java console output, and so on.
+ /// To fix this we delegate console output from Java to .NET APIs.
+ /// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+ private void ConsoleWrite(IntPtr envPtr, IntPtr clazz, IntPtr message, bool isError)
+ {
+ try
+ {
+ if (message != IntPtr.Zero)
+ {
+ // Each domain registers it's own writer.
+ var writer = _consoleWriters.Select(x => x.Value).FirstOrDefault();
+
+ if (writer != null)
+ {
+ var env = _jvm.AttachCurrentThread();
+ var msg = env.JStringToString(message);
+
+ writer.Write(msg, isError);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ _jvm.AttachCurrentThread().ThrowToJava(e);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs
new file mode 100644
index 0000000..ef4be1e
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+ using System.Diagnostics.CodeAnalysis;
+
+ /// <summary>
+ /// Console writer.
+ /// </summary>
+ internal sealed class ConsoleWriter : MarshalByRefObject
+ {
+ /// <summary>
+ /// Writes the specified message to console.
+ /// </summary>
+ [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic",
+ Justification = "Only instance methods can be called across AppDomain boundaries.")]
+ public void Write(string message, bool isError)
+ {
+ var target = isError ? Console.Error : Console.Out;
+ target.Write(message);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs
new file mode 100644
index 0000000..da790d7
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs
@@ -0,0 +1,500 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+ using System;
+ using System.Diagnostics;
+ using System.Runtime.InteropServices;
+ using System.Security;
+ using Apache.Ignite.Core.Common;
+
+ /// <summary>
+ /// JNIEnv.
+ /// </summary>
+ [SuppressUnmanagedCodeSecurity]
+ internal sealed unsafe class Env
+ {
+ /** JNIEnv pointer. */
+ private readonly IntPtr _envPtr;
+
+ /** JVM. */
+ private readonly Jvm _jvm;
+
+ /** */
+ private readonly EnvDelegates.CallStaticVoidMethod _callStaticVoidMethod;
+
+ /** */
+ private readonly EnvDelegates.CallStaticBooleanMethod _callStaticBoolMethod;
+
+ /** */
+ private readonly EnvDelegates.FindClass _findClass;
+
+ /** */
+ private readonly EnvDelegates.GetMethodId _getMethodId;
+
+ /** */
+ private readonly EnvDelegates.GetStaticMethodId _getStaticMethodId;
+
+ /** */
+ private readonly EnvDelegates.NewStringUtf _newStringUtf;
+
+ /** */
+ private readonly EnvDelegates.ExceptionOccurred _exceptionOccurred;
+
+ /** */
+ private readonly EnvDelegates.GetObjectClass _getObjectClass;
+
+ /** */
+ private readonly EnvDelegates.CallObjectMethod _callObjectMethod;
+
+ /** */
+ private readonly EnvDelegates.CallLongMethod _callLongMethod;
+
+ /** */
+ private readonly EnvDelegates.CallVoidMethod _callVoidMethod;
+
+ /** */
+ private readonly EnvDelegates.GetStringChars _getStringChars;
+
+ /** */
+ private readonly EnvDelegates.GetStringUtfChars _getStringUtfChars;
+
+ /** */
+ private readonly EnvDelegates.GetStringUtfLength _getStringUtfLength;
+
+ /** */
+ private readonly EnvDelegates.ReleaseStringUtfChars _releaseStringUtfChars;
+
+ /** */
+ private readonly EnvDelegates.ReleaseStringChars _releaseStringChars;
+
+ /** */
+ private readonly EnvDelegates.ExceptionClear _exceptionClear;
+
+ /** */
+ private readonly EnvDelegates.ExceptionCheck _exceptionCheck;
+
+ /** */
+ private readonly EnvDelegates.CallStaticObjectMethod _callStaticObjectMethod;
+
+ /** */
+ private readonly EnvDelegates.RegisterNatives _registerNatives;
+
+ /** */
+ private readonly EnvDelegates.DeleteLocalRef _deleteLocalRef;
+
+ /** */
+ private readonly EnvDelegates.NewGlobalRef _newGlobalRef;
+
+ /** */
+ private readonly EnvDelegates.DeleteGlobalRef _deleteGlobalRef;
+
+ /** */
+ private readonly EnvDelegates.ThrowNew _throwNew;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Env" /> class.
+ /// </summary>
+ internal Env(IntPtr envPtr, Jvm jvm)
+ {
+ Debug.Assert(envPtr != IntPtr.Zero);
+ Debug.Assert(jvm != null);
+
+ _envPtr = envPtr;
+ _jvm = jvm;
+
+ var funcPtr = (EnvInterface**)envPtr;
+ var func = **funcPtr;
+
+ GetDelegate(func.CallStaticVoidMethod, out _callStaticVoidMethod);
+ GetDelegate(func.CallStaticBooleanMethod, out _callStaticBoolMethod);
+ GetDelegate(func.FindClass, out _findClass);
+ GetDelegate(func.GetMethodID, out _getMethodId);
+ GetDelegate(func.GetStaticMethodID, out _getStaticMethodId);
+ GetDelegate(func.NewStringUTF, out _newStringUtf);
+ GetDelegate(func.ExceptionOccurred, out _exceptionOccurred);
+ GetDelegate(func.ExceptionClear, out _exceptionClear);
+ GetDelegate(func.ExceptionCheck, out _exceptionCheck);
+ GetDelegate(func.GetObjectClass, out _getObjectClass);
+ GetDelegate(func.CallObjectMethod, out _callObjectMethod);
+ GetDelegate(func.CallStaticObjectMethod, out _callStaticObjectMethod);
+ GetDelegate(func.CallLongMethod, out _callLongMethod);
+ GetDelegate(func.CallVoidMethod, out _callVoidMethod);
+
+ GetDelegate(func.GetStringChars, out _getStringChars);
+ GetDelegate(func.ReleaseStringChars, out _releaseStringChars);
+
+ GetDelegate(func.GetStringUTFChars, out _getStringUtfChars);
+ GetDelegate(func.ReleaseStringUTFChars, out _releaseStringUtfChars);
+
+ GetDelegate(func.GetStringUTFLength, out _getStringUtfLength);
+
+ GetDelegate(func.RegisterNatives, out _registerNatives);
+ GetDelegate(func.DeleteLocalRef, out _deleteLocalRef);
+ GetDelegate(func.NewGlobalRef, out _newGlobalRef);
+ GetDelegate(func.DeleteGlobalRef, out _deleteGlobalRef);
+ GetDelegate(func.ThrowNew, out _throwNew);
+ }
+
+ /// <summary>
+ /// Gets the JVM.
+ /// </summary>
+ public Jvm Jvm
+ {
+ get { return _jvm; }
+ }
+
+ /// <summary>
+ /// Calls the static void method.
+ /// </summary>
+ public void CallStaticVoidMethod(GlobalRef cls, IntPtr methodId, long* argsPtr = null)
+ {
+ _callStaticVoidMethod(_envPtr, cls.Target, methodId, argsPtr);
+
+ ExceptionCheck();
+ }
+
+ /// <summary>
+ /// Calls the static bool method.
+ /// </summary>
+ public bool CallStaticBoolMethod(GlobalRef cls, IntPtr methodId, long* argsPtr = null)
+ {
+ var res = _callStaticBoolMethod(_envPtr, cls.Target, methodId, argsPtr);
+
+ ExceptionCheck();
+
+ return res > 0;
+ }
+
+ /// <summary>
+ /// Calls the object method.
+ /// </summary>
+ public GlobalRef CallObjectMethod(GlobalRef obj, IntPtr methodId, long* argsPtr = null)
+ {
+ var lref = _callObjectMethod(_envPtr, obj.Target, methodId, argsPtr);
+
+ ExceptionCheck();
+
+ return NewGlobalRef(lref);
+ }
+
+ /// <summary>
+ /// Calls the long method.
+ /// </summary>
+ public long CallLongMethod(GlobalRef obj, IntPtr methodId, long* argsPtr = null)
+ {
+ var res = _callLongMethod(_envPtr, obj.Target, methodId, argsPtr);
+
+ ExceptionCheck();
+
+ return res;
+ }
+
+ /// <summary>
+ /// Calls the void method.
+ /// </summary>
+ public void CallVoidMethod(GlobalRef obj, IntPtr methodId, long* argsPtr = null)
+ {
+ _callVoidMethod(_envPtr, obj.Target, methodId, argsPtr);
+
+ ExceptionCheck();
+ }
+
+ /// <summary>
+ /// Calls the static object method.
+ /// </summary>
+ private GlobalRef CallStaticObjectMethod(GlobalRef cls, IntPtr methodId, long* argsPtr = null)
+ {
+ var res = _callStaticObjectMethod(_envPtr, cls.Target, methodId, argsPtr);
+
+ ExceptionCheck();
+
+ return NewGlobalRef(res);
+ }
+
+ /// <summary>
+ /// Finds the class.
+ /// </summary>
+ public GlobalRef FindClass(string name)
+ {
+ var res = _findClass(_envPtr, name);
+
+ if (res == IntPtr.Zero)
+ {
+ throw new IgniteException("Java class is not found (did you set IGNITE_HOME environment " +
+ "variable?): " + name);
+ }
+
+ return NewGlobalRef(res);
+ }
+
+ /// <summary>
+ /// Gets the object class.
+ /// </summary>
+ private GlobalRef GetObjectClass(GlobalRef obj)
+ {
+ var res = _getObjectClass(_envPtr, obj.Target);
+
+ ExceptionCheck();
+
+ return NewGlobalRef(res);
+ }
+
+ /// <summary>
+ /// Gets the static method identifier.
+ /// </summary>
+ public IntPtr GetStaticMethodId(GlobalRef clazz, string name, string signature)
+ {
+ var res = _getStaticMethodId(_envPtr, clazz.Target, name, signature);
+
+ if (res == IntPtr.Zero)
+ {
+ throw new IgniteException("Java class method is not found (did you set IGNITE_HOME environment " +
+ "variable?): " + name + " " + signature);
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// Gets the method identifier.
+ /// </summary>
+ public IntPtr GetMethodId(GlobalRef clazz, string name, string signature)
+ {
+ var res = _getMethodId(_envPtr, clazz.Target, name, signature);
+
+ if (res == IntPtr.Zero)
+ {
+ throw new IgniteException("Java class method is not found (did you set IGNITE_HOME environment " +
+ "variable?): " + name + " " + signature);
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// Creates new jstring from UTF chars.
+ /// </summary>
+ private GlobalRef NewStringUtf(sbyte* utf)
+ {
+ if (utf == null)
+ {
+ return null;
+ }
+
+ var res = _newStringUtf(_envPtr, new IntPtr(utf));
+
+ ExceptionCheck();
+
+ return NewGlobalRef(res);
+ }
+
+ /// <summary>
+ /// Creates new jstring from string.
+ /// </summary>
+ public GlobalRef NewStringUtf(string str)
+ {
+ if (str == null)
+ {
+ return null;
+ }
+
+ var chars = IgniteUtils.StringToUtf8Unmanaged(str);
+
+ try
+ {
+ return NewStringUtf(chars);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(new IntPtr(chars));
+ }
+ }
+
+ /// <summary>
+ /// Gets the utf chars from jstring.
+ /// </summary>
+ private IntPtr GetStringUtfChars(IntPtr jstring)
+ {
+ Debug.Assert(jstring != IntPtr.Zero);
+
+ byte isCopy;
+ return _getStringUtfChars(_envPtr, jstring, &isCopy);
+ }
+
+ /// <summary>
+ /// Releases the string utf chars allocated by <see cref="GetStringUtfChars"/>.
+ /// </summary>
+ private void ReleaseStringUtfChars(IntPtr jstring, IntPtr chars)
+ {
+ _releaseStringUtfChars(_envPtr, jstring, chars);
+ }
+
+ /// <summary>
+ /// Gets the length of the jstring.
+ /// </summary>
+ private int GetStringUtfLength(IntPtr jstring)
+ {
+ Debug.Assert(jstring != IntPtr.Zero);
+
+ return _getStringUtfLength(_envPtr, jstring);
+ }
+
+ /// <summary>
+ /// Registers the native callbacks.
+ /// </summary>
+ public void RegisterNatives(GlobalRef clazz, NativeMethod[] methods)
+ {
+ Debug.Assert(methods != null);
+
+ fixed (NativeMethod* m = &methods[0])
+ {
+ var res = _registerNatives(_envPtr, clazz.Target, m, methods.Length);
+
+ if (res != JniResult.Success)
+ {
+ throw new IgniteException("Failed to register natives: " + res);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Converts jstring to string.
+ /// </summary>
+ private string JStringToString(GlobalRef jstring)
+ {
+ if (jstring == null)
+ {
+ return null;
+ }
+
+ return JStringToString(jstring.Target);
+ }
+
+ /// <summary>
+ /// Converts jstring to string.
+ /// </summary>
+ public string JStringToString(IntPtr jstring)
+ {
+ if (jstring == IntPtr.Zero)
+ {
+ return null;
+ }
+
+ var chars = GetStringUtfChars(jstring);
+ var len = GetStringUtfLength(jstring);
+
+ try
+ {
+ return IgniteUtils.Utf8UnmanagedToString((sbyte*) chars, len);
+ }
+ finally
+ {
+ ReleaseStringUtfChars(jstring, chars);
+ }
+ }
+
+ /// <summary>
+ /// Creates a new global reference from a local reference pointer.
+ /// </summary>
+ public GlobalRef NewGlobalRef(IntPtr lref)
+ {
+ if (lref == IntPtr.Zero)
+ {
+ return null;
+ }
+
+ var res = new GlobalRef(_newGlobalRef(_envPtr, lref), _jvm);
+
+ _deleteLocalRef(_envPtr, lref);
+
+ return res;
+ }
+
+ /// <summary>
+ /// Deletes the global reference.
+ /// </summary>
+ public void DeleteGlobalRef(IntPtr gref)
+ {
+ _deleteGlobalRef(_envPtr, gref);
+ }
+
+ /// <summary>
+ /// Throws an exception to java.
+ /// </summary>
+ public void ThrowToJava(Exception e)
+ {
+ Debug.Assert(e != null);
+ var msgChars = IgniteUtils.StringToUtf8Unmanaged(e.Message);
+
+ try
+ {
+ using (var cls = FindClass("org/apache/ignite/IgniteException"))
+ {
+ _throwNew(_envPtr, cls.Target, new IntPtr(msgChars));
+ }
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(new IntPtr(msgChars));
+ }
+ }
+
+ /// <summary>
+ /// Checks for the JNI exception and throws.
+ /// </summary>
+ private void ExceptionCheck()
+ {
+ if (!_exceptionCheck(_envPtr))
+ {
+ return;
+ }
+
+ var err = _exceptionOccurred(_envPtr);
+ Debug.Assert(err != IntPtr.Zero);
+
+ _exceptionClear(_envPtr);
+
+ using (var errRef = NewGlobalRef(err))
+ {
+ var errRef0 = (long) errRef.Target;
+ var methodId = _jvm.MethodId;
+
+ using (var cls = GetObjectClass(errRef))
+ using (var clsName = CallObjectMethod(cls, methodId.ClassGetName))
+ using (var msg = CallObjectMethod(errRef, methodId.ThrowableGetMessage))
+ using (var trace = CallStaticObjectMethod(methodId.PlatformUtils,
+ methodId.PlatformUtilsGetStackTrace, &errRef0))
+ {
+ throw new JavaException(
+ JStringToString(clsName),
+ JStringToString(msg),
+ JStringToString(trace));
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the delegate.
+ /// </summary>
+ private static void GetDelegate<T>(IntPtr ptr, out T del)
+ {
+ del = (T) (object) Marshal.GetDelegateForFunctionPointer(ptr, typeof(T));
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvDelegates.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvDelegates.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvDelegates.cs
new file mode 100644
index 0000000..a2ad499
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvDelegates.cs
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ /// <summary>
+ /// Delegates for JNI Env entity.
+ /// </summary>
+ internal static unsafe class EnvDelegates
+ {
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ public delegate JniResult CallStaticVoidMethod(
+ IntPtr env, IntPtr clazz, IntPtr methodId, long* argsPtr);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate byte CallStaticBooleanMethod(
+ IntPtr env, IntPtr clazz, IntPtr methodId, long* argsPtr);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate IntPtr NewGlobalRef(IntPtr env, IntPtr lobj);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate void DeleteLocalRef(IntPtr env, IntPtr lref);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate void DeleteGlobalRef(IntPtr env, IntPtr gref);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate IntPtr FindClass(IntPtr env, [MarshalAs(UnmanagedType.LPStr)] string name);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate IntPtr GetStaticMethodId(IntPtr env, IntPtr clazz,
+ [MarshalAs(UnmanagedType.LPStr)] string name, [MarshalAs(UnmanagedType.LPStr)] string sig);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate IntPtr GetMethodId(IntPtr env, IntPtr clazz, [MarshalAs(UnmanagedType.LPStr)] string name,
+ [MarshalAs(UnmanagedType.LPStr)] string sig);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate IntPtr NewStringUtf(IntPtr env, IntPtr utf);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate IntPtr ExceptionOccurred(IntPtr env);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate void ExceptionClear(IntPtr env);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate bool ExceptionCheck(IntPtr env);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate IntPtr GetObjectClass(IntPtr env, IntPtr obj);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate IntPtr CallObjectMethod(
+ IntPtr env, IntPtr obj, IntPtr methodId, long* argsPtr);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate long CallLongMethod(
+ IntPtr env, IntPtr obj, IntPtr methodId, long* argsPtr);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate void CallVoidMethod(
+ IntPtr env, IntPtr obj, IntPtr methodId, long* argsPtr);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate IntPtr CallStaticObjectMethod(
+ IntPtr env, IntPtr clazz, IntPtr methodId, long* argsPtr);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate IntPtr GetStringChars(IntPtr env, IntPtr jstring, byte* isCopy);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate void ReleaseStringChars(IntPtr env, IntPtr jstring, IntPtr chars);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate IntPtr GetStringUtfChars(IntPtr env, IntPtr jstring, byte* isCopy);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate void ReleaseStringUtfChars(IntPtr env, IntPtr jstring, IntPtr chars);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate int GetStringUtfLength(IntPtr env, IntPtr jstring);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate JniResult RegisterNatives(IntPtr env, IntPtr clazz,
+ NativeMethod* methods, int nMethods);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate JniResult ThrowNew(IntPtr env, IntPtr clazz, IntPtr msg);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvInterface.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvInterface.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvInterface.cs
new file mode 100644
index 0000000..01f8634
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvInterface.cs
@@ -0,0 +1,263 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ /// <summary>
+ /// JNIEnv interface.
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct EnvInterface
+ {
+ // ReSharper disable MemberCanBePrivate.Global
+ public IntPtr reserved0;
+ public IntPtr reserved1;
+ public IntPtr reserved2;
+ public IntPtr reserved3;
+ public IntPtr GetVersion;
+ public IntPtr DefineClass;
+ public IntPtr FindClass;
+ public IntPtr FromReflectedMethod;
+ public IntPtr FromReflectedField;
+ public IntPtr ToReflectedMethod;
+ public IntPtr GetSuperclass;
+ public IntPtr IsAssignableFrom;
+ public IntPtr ToReflectedField;
+ public IntPtr Throw;
+ public IntPtr ThrowNew;
+ public IntPtr ExceptionOccurred;
+ public IntPtr ExceptionDescribe;
+ public IntPtr ExceptionClear;
+ public IntPtr FatalError;
+ public IntPtr PushLocalFrame;
+ public IntPtr PopLocalFrame;
+ public IntPtr NewGlobalRef;
+ public IntPtr DeleteGlobalRef;
+ public IntPtr DeleteLocalRef;
+ public IntPtr IsSameObject;
+ public IntPtr NewLocalRef;
+ public IntPtr EnsureLocalCapacity;
+ public IntPtr AllocObject;
+ public IntPtr __NewObject;
+ public IntPtr __NewObjectV;
+ public IntPtr NewObject;
+ public IntPtr GetObjectClass;
+ public IntPtr IsInstanceOf;
+ public IntPtr GetMethodID;
+ public IntPtr __CallObjectMethod;
+ public IntPtr __CallObjectMethodV;
+ public IntPtr CallObjectMethod;
+ public IntPtr __CallBooleanMethod;
+ public IntPtr __CallBooleanMethodV;
+ public IntPtr CallBooleanMethod;
+ public IntPtr __CallByteMethod;
+ public IntPtr __CallByteMethodV;
+ public IntPtr CallByteMethod;
+ public IntPtr __CallCharMethod;
+ public IntPtr __CallCharMethodV;
+ public IntPtr CallCharMethod;
+ public IntPtr __CallShortMethod;
+ public IntPtr __CallShortMethodV;
+ public IntPtr CallShortMethod;
+ public IntPtr __CallIntMethod;
+ public IntPtr __CallIntMethodV;
+ public IntPtr CallIntMethod;
+ public IntPtr __CallLongMethod;
+ public IntPtr __CallLongMethodV;
+ public IntPtr CallLongMethod;
+ public IntPtr __CallFloatMethod;
+ public IntPtr __CallFloatMethodV;
+ public IntPtr CallFloatMethod;
+ public IntPtr __CallDoubleMethod;
+ public IntPtr __CallDoubleMethodV;
+ public IntPtr CallDoubleMethod;
+ public IntPtr __CallVoidMethod;
+ public IntPtr __CallVoidMethodV;
+ public IntPtr CallVoidMethod;
+ public IntPtr __CallNonvirtualObjectMethod;
+ public IntPtr __CallNonvirtualObjectMethodV;
+ public IntPtr CallNonvirtualObjectMethod;
+ public IntPtr __CallNonvirtualBooleanMethod;
+ public IntPtr __CallNonvirtualBooleanMethodV;
+ public IntPtr CallNonvirtualBooleanMethod;
+ public IntPtr __CallNonvirtualByteMethod;
+ public IntPtr __CallNonvirtualByteMethodV;
+ public IntPtr CallNonvirtualByteMethod;
+ public IntPtr __CallNonvirtualCharMethod;
+ public IntPtr __CallNonvirtualCharMethodV;
+ public IntPtr CallNonvirtualCharMethod;
+ public IntPtr __CallNonvirtualShortMethod;
+ public IntPtr __CallNonvirtualShortMethodV;
+ public IntPtr CallNonvirtualShortMethod;
+ public IntPtr __CallNonvirtualIntMethod;
+ public IntPtr __CallNonvirtualIntMethodV;
+ public IntPtr CallNonvirtualIntMethod;
+ public IntPtr __CallNonvirtualLongMethod;
+ public IntPtr __CallNonvirtualLongMethodV;
+ public IntPtr CallNonvirtualLongMethod;
+ public IntPtr __CallNonvirtualFloatMethod;
+ public IntPtr __CallNonvirtualFloatMethodV;
+ public IntPtr CallNonvirtualFloatMethod;
+ public IntPtr __CallNonvirtualDoubleMethod;
+ public IntPtr __CallNonvirtualDoubleMethodV;
+ public IntPtr CallNonvirtualDoubleMethod;
+ public IntPtr __CallNonvirtualVoidMethod;
+ public IntPtr __CallNonvirtualVoidMethodV;
+ public IntPtr CallNonvirtualVoidMethod;
+ public IntPtr GetFieldID;
+ public IntPtr GetObjectField;
+ public IntPtr GetBooleanField;
+ public IntPtr GetByteField;
+ public IntPtr GetCharField;
+ public IntPtr GetShortField;
+ public IntPtr GetIntField;
+ public IntPtr GetLongField;
+ public IntPtr GetFloatField;
+ public IntPtr GetDoubleField;
+ public IntPtr SetObjectField;
+ public IntPtr SetBooleanField;
+ public IntPtr SetByteField;
+ public IntPtr SetCharField;
+ public IntPtr SetShortField;
+ public IntPtr SetIntField;
+ public IntPtr SetLongField;
+ public IntPtr SetFloatField;
+ public IntPtr SetDoubleField;
+ public IntPtr GetStaticMethodID;
+ public IntPtr __CallStaticObjectMethod;
+ public IntPtr __CallStaticObjectMethodV;
+ public IntPtr CallStaticObjectMethod;
+ public IntPtr __CallStaticBooleanMethod;
+ public IntPtr __CallStaticBooleanMethodV;
+ public IntPtr CallStaticBooleanMethod;
+ public IntPtr __CallStaticByteMethod;
+ public IntPtr __CallStaticByteMethodV;
+ public IntPtr CallStaticByteMethod;
+ public IntPtr __CallStaticCharMethod;
+ public IntPtr __CallStaticCharMethodV;
+ public IntPtr CallStaticCharMethod;
+ public IntPtr __CallStaticShortMethod;
+ public IntPtr __CallStaticShortMethodV;
+ public IntPtr CallStaticShortMethod;
+ public IntPtr __CallStaticIntMethod;
+ public IntPtr __CallStaticIntMethodV;
+ public IntPtr CallStaticIntMethod;
+ public IntPtr __CallStaticLongMethod;
+ public IntPtr __CallStaticLongMethodV;
+ public IntPtr CallStaticLongMethod;
+ public IntPtr __CallStaticFloatMethod;
+ public IntPtr __CallStaticFloatMethodV;
+ public IntPtr CallStaticFloatMethod;
+ public IntPtr __CallStaticDoubleMethod;
+ public IntPtr __CallStaticDoubleMethodV;
+ public IntPtr CallStaticDoubleMethod;
+ public IntPtr __CallStaticVoidMethod;
+ public IntPtr __CallStaticVoidMethodV;
+ public IntPtr CallStaticVoidMethod;
+ public IntPtr GetStaticFieldID;
+ public IntPtr GetStaticObjectField;
+ public IntPtr GetStaticBooleanField;
+ public IntPtr GetStaticByteField;
+ public IntPtr GetStaticCharField;
+ public IntPtr GetStaticShortField;
+ public IntPtr GetStaticIntField;
+ public IntPtr GetStaticLongField;
+ public IntPtr GetStaticFloatField;
+ public IntPtr GetStaticDoubleField;
+ public IntPtr SetStaticObjectField;
+ public IntPtr SetStaticBooleanField;
+ public IntPtr SetStaticByteField;
+ public IntPtr SetStaticCharField;
+ public IntPtr SetStaticShortField;
+ public IntPtr SetStaticIntField;
+ public IntPtr SetStaticLongField;
+ public IntPtr SetStaticFloatField;
+ public IntPtr SetStaticDoubleField;
+ public IntPtr NewString;
+ public IntPtr GetStringLength;
+ public IntPtr GetStringChars;
+ public IntPtr ReleaseStringChars;
+ public IntPtr NewStringUTF;
+ public IntPtr GetStringUTFLength;
+ public IntPtr GetStringUTFChars;
+ public IntPtr ReleaseStringUTFChars;
+ public IntPtr GetArrayLength;
+ public IntPtr NewObjectArray;
+ public IntPtr GetObjectArrayElement;
+ public IntPtr SetObjectArrayElement;
+ public IntPtr NewBooleanArray;
+ public IntPtr NewByteArray;
+ public IntPtr NewCharArray;
+ public IntPtr NewShortArray;
+ public IntPtr NewIntArray;
+ public IntPtr NewLongArray;
+ public IntPtr NewFloatArray;
+ public IntPtr NewDoubleArray;
+ public IntPtr GetBooleanArrayElements;
+ public IntPtr GetByteArrayElements;
+ public IntPtr GetCharArrayElements;
+ public IntPtr GetShortArrayElements;
+ public IntPtr GetIntArrayElements;
+ public IntPtr GetLongArrayElements;
+ public IntPtr GetFloatArrayElements;
+ public IntPtr GetDoubleArrayElements;
+ public IntPtr ReleaseBooleanArrayElements;
+ public IntPtr ReleaseByteArrayElements;
+ public IntPtr ReleaseCharArrayElements;
+ public IntPtr ReleaseShortArrayElements;
+ public IntPtr ReleaseIntArrayElements;
+ public IntPtr ReleaseLongArrayElements;
+ public IntPtr ReleaseFloatArrayElements;
+ public IntPtr ReleaseDoubleArrayElements;
+ public IntPtr GetBooleanArrayRegion;
+ public IntPtr GetByteArrayRegion;
+ public IntPtr GetCharArrayRegion;
+ public IntPtr GetShortArrayRegion;
+ public IntPtr GetIntArrayRegion;
+ public IntPtr GetLongArrayRegion;
+ public IntPtr GetFloatArrayRegion;
+ public IntPtr GetDoubleArrayRegion;
+ public IntPtr SetBooleanArrayRegion;
+ public IntPtr SetByteArrayRegion;
+ public IntPtr SetCharArrayRegion;
+ public IntPtr SetShortArrayRegion;
+ public IntPtr SetIntArrayRegion;
+ public IntPtr SetLongArrayRegion;
+ public IntPtr SetFloatArrayRegion;
+ public IntPtr SetDoubleArrayRegion;
+ public IntPtr RegisterNatives;
+ public IntPtr UnregisterNatives;
+ public IntPtr MonitorEnter;
+ public IntPtr MonitorExit;
+ public IntPtr GetJavaVM;
+ public IntPtr GetStringRegion;
+ public IntPtr GetStringUTFRegion;
+ public IntPtr GetPrimitiveArrayCritical;
+ public IntPtr ReleasePrimitiveArrayCritical;
+ public IntPtr GetStringCritical;
+ public IntPtr ReleaseStringCritical;
+ public IntPtr NewWeakGlobalRef;
+ public IntPtr DeleteWeakGlobalRef;
+ public IntPtr ExceptionCheck;
+ public IntPtr NewDirectByteBuffer;
+ public IntPtr GetDirectBufferAddress;
+ public IntPtr GetDirectBufferCapacity;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/GlobalRef.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/GlobalRef.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/GlobalRef.cs
new file mode 100644
index 0000000..c33a53b
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/GlobalRef.cs
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+ using System.Diagnostics;
+
+ /// <summary>
+ /// JNI Global Reference.
+ /// <para />
+ /// We should always convert local reference to global and delete local one immediately,
+ /// otherwise these local references may cause memory leaks (false GC roots).
+ /// </summary>
+ internal sealed class GlobalRef : IDisposable
+ {
+ /** Reference. */
+ private readonly IntPtr _target;
+
+ /** JVM. */
+ private readonly Jvm _jvm;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="GlobalRef"/> class.
+ /// </summary>
+ public GlobalRef(IntPtr target, Jvm jvm)
+ {
+ Debug.Assert(target != IntPtr.Zero);
+ Debug.Assert(jvm != null);
+
+ _target = target;
+ _jvm = jvm;
+ }
+
+ /// <summary>
+ /// Gets the target.
+ /// </summary>
+ public IntPtr Target
+ {
+ get { return _target; }
+ }
+
+ /// <summary>
+ /// Gets the JVM.
+ /// </summary>
+ public Jvm Jvm
+ {
+ get { return _jvm; }
+ }
+
+ /// <summary>
+ /// Releases the unmanaged resources.
+ /// </summary>
+ private void ReleaseUnmanagedResources()
+ {
+ _jvm.AttachCurrentThread().DeleteGlobalRef(_target);
+ }
+
+ /** <inheritdoc /> */
+ public void Dispose()
+ {
+ ReleaseUnmanagedResources();
+ GC.SuppressFinalize(this);
+ }
+
+ /** <inheritdoc /> */
+ ~GlobalRef()
+ {
+ ReleaseUnmanagedResources();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JniResult.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JniResult.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JniResult.cs
new file mode 100644
index 0000000..0370d5c
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JniResult.cs
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+ /// <summary>
+ /// JNI call result.
+ /// </summary>
+ internal enum JniResult
+ {
+ Success = 0,
+ // ReSharper disable UnusedMember.Global
+ // Some statuses are not used directly, but will be displayed as part of error message.
+ Error = -1,
+ ThreadDetached = -2,
+ VersionError = -3,
+ NotEnoughMemory = -4,
+ AlreadyExists = -5,
+ InvalidArguments = -6
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs
new file mode 100644
index 0000000..10c7468
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs
@@ -0,0 +1,335 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Reflection;
+ using System.Runtime.InteropServices;
+ using System.Security;
+ using System.Threading;
+ using Apache.Ignite.Core.Common;
+
+ /// <summary>
+ /// JVM holder. Should exist once per domain.
+ /// </summary>
+ [SuppressUnmanagedCodeSecurity]
+ internal sealed unsafe class Jvm
+ {
+ /** */
+ // ReSharper disable once InconsistentNaming
+ private const int JNI_VERSION_1_6 = 0x00010006;
+
+ /** */
+ private readonly IntPtr _jvmPtr;
+
+ /** */
+ private readonly JvmDelegates.AttachCurrentThread _attachCurrentThread;
+
+ /** */
+ private readonly MethodId _methodId;
+
+ /** Callbacks. */
+ private readonly Callbacks _callbacks;
+
+ /** Static instamce */
+ private static volatile Jvm _instance;
+
+ /** Sync. */
+ private static readonly object SyncRoot = new object();
+
+ /** Console writer. */
+ private static readonly ConsoleWriter ConsoleWriter = new ConsoleWriter();
+
+ /** Env for current thread. */
+ [ThreadStatic] private static Env _env;
+
+ /** Console writer flag. */
+ private int _isConsoleWriterEnabled;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="_instance"/> class.
+ /// </summary>
+ private Jvm(IntPtr jvmPtr)
+ {
+ Debug.Assert(jvmPtr != IntPtr.Zero);
+
+ _jvmPtr = jvmPtr;
+
+ var funcPtr = (JvmInterface**)jvmPtr;
+ var func = **funcPtr;
+ GetDelegate(func.AttachCurrentThread, out _attachCurrentThread);
+
+ var env = AttachCurrentThread();
+ _methodId = new MethodId(env);
+ _callbacks = GetCallbacks(env, this);
+ }
+
+ /// <summary>
+ /// Gets the callbacks.
+ /// </summary>
+ private static Callbacks GetCallbacks(Env env, Jvm jvm)
+ {
+ if (AppDomain.CurrentDomain.IsDefaultAppDomain())
+ {
+ return new Callbacks(env, jvm);
+ }
+
+ // JVM exists once per process, and JVM callbacks exist once per process.
+ // We should register callbacks ONLY from the default AppDomain (which can't be unloaded).
+ // Non-default appDomains should delegate this logic to the default one.
+ var defDomain = AppDomains.GetDefaultAppDomain();
+
+ // In some cases default AppDomain is not able to locate Apache.Ignite.Core assembly.
+ // First, use CreateInstanceFrom to set up the AssemblyResolve handler.
+ var resHelpType = typeof(AssemblyResolver);
+ var resHelp = (AssemblyResolver)defDomain.CreateInstanceFrom(resHelpType.Assembly.Location, resHelpType.FullName)
+ .Unwrap();
+ resHelp.TrackResolve(resHelpType.Assembly.FullName, resHelpType.Assembly.Location);
+
+ // Now use CreateInstance to get the domain helper of a properly loaded class.
+ var type = typeof(CallbackAccessor);
+ var helper = (CallbackAccessor)defDomain.CreateInstance(type.Assembly.FullName, type.FullName).Unwrap();
+
+ return helper.GetCallbacks();
+ }
+
+ /// <summary>
+ /// Gets or creates the JVM.
+ /// </summary>
+ /// <param name="options">JVM options.</param>
+ public static Jvm GetOrCreate(IList<string> options)
+ {
+ lock (SyncRoot)
+ {
+ return _instance ?? (_instance = new Jvm(GetJvmPtr(options)));
+ }
+ }
+
+ /// <summary>
+ /// Gets the JVM.
+ /// </summary>
+ public static Jvm Get()
+ {
+ var res = _instance;
+
+ if (res == null)
+ {
+ throw new IgniteException("JVM has not been created.");
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// Gets the method IDs.
+ /// </summary>
+ public MethodId MethodId
+ {
+ get { return _methodId; }
+ }
+
+ /// <summary>
+ /// Attaches current thread to the JVM and returns JNIEnv.
+ /// </summary>
+ public Env AttachCurrentThread()
+ {
+ if (_env == null)
+ {
+ IntPtr envPtr;
+ var res = _attachCurrentThread(_jvmPtr, out envPtr, IntPtr.Zero);
+
+ if (res != JniResult.Success)
+ {
+ throw new IgniteException("AttachCurrentThread failed: " + res);
+ }
+
+ _env = new Env(envPtr, this);
+ }
+
+ return _env;
+ }
+
+ /// <summary>
+ /// Registers the callbacks.
+ /// </summary>
+ public void RegisterCallbacks(UnmanagedCallbacks cbs)
+ {
+ var id = _callbacks.RegisterHandlers(cbs);
+ cbs.SetContext(id);
+ }
+
+ /// <summary>
+ /// Releases the callbacks.
+ /// </summary>
+ public void ReleaseCallbacks(long igniteId)
+ {
+ _callbacks.ReleaseHandlers(igniteId);
+ }
+
+ /// <summary>
+ /// Enables the Java console output propagation.
+ /// </summary>
+ public void EnableJavaConsoleWriter()
+ {
+ if (Interlocked.CompareExchange(ref _isConsoleWriterEnabled, 1, 0) == 0)
+ {
+ var writerId = _callbacks.RegisterConsoleWriter(ConsoleWriter);
+ AppDomain.CurrentDomain.DomainUnload += (s, a) => _callbacks.ReleaseConsoleWriter(writerId);
+ }
+ }
+
+ /// <summary>
+ /// Gets the JVM pointer.
+ /// </summary>
+ private static IntPtr GetJvmPtr(IList<string> options)
+ {
+ IntPtr jvm;
+ int existingJvmCount;
+
+ // Use existing JVM if present.
+ var res = JniNativeMethods.JNI_GetCreatedJavaVMs(out jvm, 1, out existingJvmCount);
+ if (res != JniResult.Success)
+ {
+ throw new IgniteException("JNI_GetCreatedJavaVMs failed: " + res);
+ }
+
+ if (existingJvmCount > 0)
+ {
+ return jvm;
+ }
+
+ var args = new JvmInitArgs
+ {
+ version = JNI_VERSION_1_6
+ };
+
+ if (options != null && options.Count > 0)
+ {
+ args.nOptions = options.Count;
+ var opt = new JvmOption[options.Count];
+
+ for (int i = 0; i < options.Count; i++)
+ {
+ opt[i].optionString = Marshal.StringToHGlobalAnsi(options[i]);
+ }
+
+ fixed (JvmOption* a = &opt[0])
+ {
+ args.options = a;
+ }
+ }
+
+ IntPtr env;
+ res = JniNativeMethods.JNI_CreateJavaVM(out jvm, out env, &args);
+ if (res != JniResult.Success)
+ {
+ throw new IgniteException("JNI_CreateJavaVM failed: " + res);
+ }
+
+ return jvm;
+ }
+
+ /// <summary>
+ /// Gets the delegate.
+ /// </summary>
+ private static void GetDelegate<T>(IntPtr ptr, out T del)
+ {
+ del = (T) (object) Marshal.GetDelegateForFunctionPointer(ptr, typeof(T));
+ }
+
+ /// <summary>
+ /// JavaVMOption.
+ /// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")]
+ [StructLayout(LayoutKind.Sequential, Pack = 0)]
+ private struct JvmOption
+ {
+ public IntPtr optionString;
+ private readonly IntPtr extraInfo;
+ }
+
+ /// <summary>
+ /// JavaVMInitArgs.
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential, Pack = 0)]
+ private struct JvmInitArgs
+ {
+ public int version;
+ public int nOptions;
+ public JvmOption* options;
+ private readonly byte ignoreUnrecognized;
+ }
+
+ /// <summary>
+ /// DLL imports.
+ /// </summary>
+ private static class JniNativeMethods
+ {
+ [DllImport("jvm.dll", CallingConvention = CallingConvention.StdCall)]
+ internal static extern JniResult JNI_CreateJavaVM(out IntPtr pvm, out IntPtr penv,
+ JvmInitArgs* args);
+
+ [DllImport("jvm.dll", CallingConvention = CallingConvention.StdCall)]
+ internal static extern JniResult JNI_GetCreatedJavaVMs(out IntPtr pvm, int size,
+ [Out] out int size2);
+ }
+
+ /// <summary>
+ /// Provides access to <see cref="Callbacks"/> instance in the default AppDomain.
+ /// </summary>
+ private class CallbackAccessor : MarshalByRefObject
+ {
+ /// <summary>
+ /// Gets the callbacks.
+ /// </summary>
+ [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic",
+ Justification = "Only instance methods can be called across AppDomain boundaries.")]
+ public Callbacks GetCallbacks()
+ {
+ return GetOrCreate(null)._callbacks;
+ }
+ }
+
+ /// <summary>
+ /// Resolves Apache.Ignite.Core assembly in the default AppDomain when needed.
+ /// </summary>
+ private class AssemblyResolver : MarshalByRefObject
+ {
+ /// <summary>
+ /// Tracks the AssemblyResolve event.
+ /// </summary>
+ [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic",
+ Justification = "Only instance methods can be called across AppDomain boundaries.")]
+ public void TrackResolve(string name, string path)
+ {
+ AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
+ {
+ if (args.Name == name)
+ {
+ return Assembly.LoadFrom(path);
+ }
+
+ return null;
+ };
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmDelegates.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmDelegates.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmDelegates.cs
new file mode 100644
index 0000000..9686888
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmDelegates.cs
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ /// <summary>
+ /// Delegates for JavaVM JNI entity.
+ /// </summary>
+ internal static class JvmDelegates
+ {
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ internal delegate JniResult AttachCurrentThread(IntPtr jvm, out IntPtr env, IntPtr args);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmInterface.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmInterface.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmInterface.cs
new file mode 100644
index 0000000..74d5ba1
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmInterface.cs
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ /// <summary>
+ /// JavaVM interface.
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct JvmInterface
+ {
+ // ReSharper disable MemberCanBePrivate.Global
+ public IntPtr reserved0;
+ public IntPtr reserved1;
+ public IntPtr reserved2;
+
+ public IntPtr DestroyJavaVM;
+ public IntPtr AttachCurrentThread;
+ public IntPtr DetachCurrentThread;
+ public IntPtr GetEnv;
+ public IntPtr AttachCurrentThreadAsDaemon;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/MethodId.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/MethodId.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/MethodId.cs
new file mode 100644
index 0000000..12a4dff
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/MethodId.cs
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+ using System;
+ using System.Diagnostics;
+
+ /// <summary>
+ /// Cached JNI method ids: initialized once on JVM start.
+ /// </summary>
+ internal sealed class MethodId
+ {
+ /// <summary>
+ /// Class.getName().
+ /// </summary>
+ public IntPtr ClassGetName { get; private set; }
+
+ /// <summary>
+ /// Throwable.getMessage().
+ /// </summary>
+ public IntPtr ThrowableGetMessage { get; private set; }
+
+ /// <summary>
+ /// PlatformIgnition.
+ /// </summary>
+ public GlobalRef PlatformIgnition { get; private set; }
+
+ /// <summary>
+ /// PlatformIgnition.start().
+ /// </summary>
+ public IntPtr PlatformIgnitionStart { get; private set; }
+
+ /// <summary>
+ /// PlatformIgnition.stop().
+ /// </summary>
+ public IntPtr PlatformIgnitionStop { get; private set; }
+
+ /// <summary>
+ /// PlatformTargetProxy.inStreamOutObjectAsync().
+ /// </summary>
+ public IntPtr TargetInStreamOutObjectAsync { get; private set; }
+
+ /// <summary>
+ /// PlatformTargetProxy.inStreamAsync().
+ /// </summary>
+ public IntPtr TargetInStreamAsync { get; private set; }
+
+ /// <summary>
+ /// PlatformTargetProxy.outObject ().
+ /// </summary>
+ public IntPtr TargetOutObject { get; private set; }
+
+ /// <summary>
+ /// PlatformTargetProxy.outStream().
+ /// </summary>
+ public IntPtr TargetOutStream { get; private set; }
+
+ /// <summary>
+ /// PlatformTargetProxy.inStreamOutStream().
+ /// </summary>
+ public IntPtr TargetInStreamOutStream { get; private set; }
+
+ /// <summary>
+ /// PlatformTargetProxy.inObjectStreamOutObjectStream().
+ /// </summary>
+ public IntPtr TargetInObjectStreamOutObjectStream { get; private set; }
+
+ /// <summary>
+ /// PlatformTargetProxy.inStreamOutObject().
+ /// </summary>
+ public IntPtr TargetInStreamOutObject { get; private set; }
+
+ /// <summary>
+ /// PlatformTargetProxy.inStreamOutLong().
+ /// </summary>
+ public IntPtr TargetInStreamOutLong { get; private set; }
+
+ /// <summary>
+ /// PlatformTargetProxy.inLongOutLong().
+ /// </summary>
+ public IntPtr TargetInLongOutLong { get; private set; }
+
+ /// <summary>
+ /// PlatformUtils class.
+ /// </summary>
+ public GlobalRef PlatformUtils { get; private set; }
+
+ /// <summary>
+ /// PlatformUtils.getFullStackTrace.
+ /// </summary>
+ public IntPtr PlatformUtilsGetStackTrace { get; private set; }
+
+ /// <summary>
+ /// PlatformUtils.reallocate.
+ /// </summary>
+ public IntPtr PlatformUtilsReallocate { get; private set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MethodId"/> class.
+ /// </summary>
+ public MethodId(Env env)
+ {
+ Debug.Assert(env != null);
+
+ using (var classCls = env.FindClass("java/lang/Class"))
+ {
+ ClassGetName = env.GetMethodId(classCls, "getName", "()Ljava/lang/String;");
+ }
+
+ using (var throwableCls = env.FindClass("java/lang/Throwable"))
+ {
+ ThrowableGetMessage = env.GetMethodId(throwableCls, "getMessage", "()Ljava/lang/String;");
+ }
+
+ PlatformIgnition = env.FindClass(
+ "org/apache/ignite/internal/processors/platform/PlatformIgnition");
+ PlatformIgnitionStart = env.GetStaticMethodId(PlatformIgnition,
+ "start", "(Ljava/lang/String;Ljava/lang/String;IJJ)V");
+ PlatformIgnitionStop = env.GetStaticMethodId(PlatformIgnition, "stop", "(Ljava/lang/String;Z)Z");
+
+ using (var target = env.FindClass("org/apache/ignite/internal/processors/platform/PlatformTargetProxy"))
+ {
+ TargetInLongOutLong = env.GetMethodId(target, "inLongOutLong", "(IJ)J");
+ TargetInStreamOutLong = env.GetMethodId(target, "inStreamOutLong", "(IJ)J");
+ TargetInStreamOutObject = env.GetMethodId(target, "inStreamOutObject", "(IJ)Ljava/lang/Object;");
+ TargetInStreamOutStream = env.GetMethodId(target, "inStreamOutStream", "(IJJ)V");
+ TargetInObjectStreamOutObjectStream = env.GetMethodId(target, "inObjectStreamOutObjectStream",
+ "(ILjava/lang/Object;JJ)Ljava/lang/Object;");
+ TargetOutStream = env.GetMethodId(target, "outStream", "(IJ)V");
+ TargetOutObject = env.GetMethodId(target, "outObject", "(I)Ljava/lang/Object;");
+ TargetInStreamAsync = env.GetMethodId(target, "inStreamAsync", "(IJ)V");
+ TargetInStreamOutObjectAsync =
+ env.GetMethodId(target, "inStreamOutObjectAsync", "(IJ)Ljava/lang/Object;");
+ }
+
+ PlatformUtils = env.FindClass("org/apache/ignite/internal/processors/platform/utils/PlatformUtils");
+ PlatformUtilsGetStackTrace = env.GetStaticMethodId(PlatformUtils, "getFullStackTrace",
+ "(Ljava/lang/Throwable;)Ljava/lang/String;");
+ PlatformUtilsReallocate = env.GetStaticMethodId(PlatformUtils, "reallocate", "(JI)V");
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/NativeMethod.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/NativeMethod.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/NativeMethod.cs
new file mode 100644
index 0000000..b8a8f89
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/NativeMethod.cs
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+#pragma warning disable 414 // Unused FuncPtr
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+ using System.Diagnostics.CodeAnalysis;
+ using System.Runtime.InteropServices;
+
+ /// <summary>
+ /// JNINativeMethod structure for registering Java -> .NET callbacks.
+ /// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")]
+ internal struct NativeMethod
+ {
+ /// <summary>
+ /// Method name, char*.
+ /// </summary>
+ public IntPtr Name;
+
+ /// <summary>
+ /// Method signature, char*.
+ /// </summary>
+ public IntPtr Signature;
+
+ /// <summary>
+ /// Function pointer (from <see cref="Marshal.GetFunctionPointerForDelegate"/>).
+ /// </summary>
+ public IntPtr FuncPtr;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbackHandlers.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbackHandlers.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbackHandlers.cs
deleted file mode 100644
index 32e0a29..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbackHandlers.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-namespace Apache.Ignite.Core.Impl.Unmanaged
-{
- using System.Runtime.InteropServices;
-
- /// <summary>
- /// Unmanaged callback handler function pointers.
- /// </summary>
- [StructLayout(LayoutKind.Sequential, Pack = 0)]
- internal unsafe struct UnmanagedCallbackHandlers
- {
- internal void* target;
-
- internal void* error;
-
- internal void* loggerLog;
- internal void* loggerIsLevelEnabled;
-
- internal void* inLongOutLong;
- internal void* inLongLongObjectOutLong;
- }
-}