ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ptupit...@apache.org
Subject [2/3] ignite git commit: IGNITE-5343 .NET: Work with JNI directly, get rid of C++ layer
Date Tue, 14 Nov 2017 14:18:06 GMT
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;
-    }
-}


Mime
View raw message