IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
JavaVM.cs
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2014 Jeroen Frijters
3
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19
20 Jeroen Frijters
21 jeroen@frijters.net
22
23*/
24using System;
25using System.Runtime.InteropServices;
26
27using IKVM.ByteCode.Text;
29
31{
32
33#if FIRST_PASS == false && IMPORTER == false && EXPORTER == false
34
35 using jint = System.Int32;
36
37 [StructLayout(LayoutKind.Sequential)]
38 unsafe struct JavaVM
39 {
40
41 static readonly MUTF8Encoding MUTF8 = MUTF8Encoding.GetMUTF8(52);
42
43 internal static JavaVM* pJavaVM;
44 void** vtable;
46 delegate int pf_int(JavaVM* pJVM);
47 delegate int pf_int_ppvoid_pvoid(JavaVM* pJVM, void** p1, void* p2);
48 delegate int pf_int_ppvoid_int(JavaVM* pJVM, void** p1, int p2);
49
50 static Delegate[] vtableDelegates =
51 {
52 null,
53 null,
54 null,
55 new pf_int(DestroyJavaVM),
56 new pf_int_ppvoid_pvoid(AttachCurrentThread),
57 new pf_int(DetachCurrentThread),
58 new pf_int_ppvoid_int(GetEnv),
59 new pf_int_ppvoid_pvoid(AttachCurrentThreadAsDaemon)
60 };
61
62 static JavaVM()
63 {
64 JNIVM.jvmCreated = true;
65 pJavaVM = (JavaVM*)(void*)JNIMemory.Alloc(IntPtr.Size * (1 + vtableDelegates.Length));
66 pJavaVM->vtable = &pJavaVM->firstVtableEntry;
67 for (int i = 0; i < vtableDelegates.Length; i++)
68 {
69 if (null != vtableDelegates[i])
70 {
71 pJavaVM->vtable[i] = (void*)Marshal.GetFunctionPointerForDelegate(vtableDelegates[i]);
72 }
73 }
74 }
75
81 internal static jint DestroyJavaVM(JavaVM* pJVM)
82 {
83 if (JNIVM.jvmDestroyed)
84 return JNIEnv.JNI_ERR;
85
86 JNIVM.jvmDestroyed = true;
87 IKVM.Java.Externs.java.lang.Thread.WaitUntilLastJniThread();
88 return JNIEnv.JNI_OK;
89 }
90
98 internal static jint AttachCurrentThread(JavaVM* pJVM, void** penv, void* args)
99 {
100 return AttachCurrentThreadImpl(pJVM, penv, (JavaVMAttachArgs*)args, false);
101 }
102
111 internal static jint AttachCurrentThreadImpl(JavaVM* pJVM, void** penv, JavaVMAttachArgs* pAttachArgs, bool asDaemon)
112 {
113 if (pAttachArgs != null)
114 {
115 if (!JNIVM.IsSupportedJNIVersion(pAttachArgs->version) || pAttachArgs->version == JNIEnv.JNI_VERSION_1_1)
116 {
117 *penv = null;
118 return JNIEnv.JNI_EVERSION;
119 }
120 }
121
122 var env = JNIEnvContext.Current;
123 if (env != null)
124 {
125 *penv = env.pJNIEnv;
126 return JNIEnv.JNI_OK;
127 }
128
129 // NOTE if we're here, it is *very* likely that the thread was created by native code and not by managed code,
130 // but it's not impossible that the thread started life as a managed thread and if it did the changes to the
131 // thread we're making are somewhat dubious.
132 System.Threading.Thread.CurrentThread.IsBackground = asDaemon;
133 if (pAttachArgs != null)
134 {
135 if (pAttachArgs->name != null && System.Threading.Thread.CurrentThread.Name == null)
136 {
137 try
138 {
139 var l = MemoryMarshalExtensions.GetIndexOfNull(pAttachArgs->name);
140 if (l < 0)
141 return JNIEnv.JNI_ERR;
142
143 System.Threading.Thread.CurrentThread.Name = MUTF8.GetString(pAttachArgs->name, l);
144 }
145 catch (InvalidOperationException)
146 {
147 // someone beat us to it...
148 }
149 }
150 var threadGroup = JNIGlobalRefTable.Unwrap(pAttachArgs->group);
151 if (threadGroup != null)
152 IKVM.Java.Externs.java.lang.Thread.AttachThreadFromJni(threadGroup);
153 }
154
155 *penv = JNIEnv.CreateJNIEnv(JVM.Context);
156 return JNIEnv.JNI_OK;
157 }
158
164 internal static jint DetachCurrentThread(JavaVM* pJVM)
165 {
166 if (JNIEnvContext.Current == null)
167 {
168 // the JDK allows detaching from an already detached thread
169 return JNIEnv.JNI_OK;
170 }
171
172 // TODO if we set Thread.IsBackground to false when we attached, now might be a good time to set it back to true.
173 JNIEnv.FreeJNIEnv();
174 java.lang.Thread.currentThread().die();
175 return JNIEnv.JNI_OK;
176 }
177
178 internal static jint GetEnv(JavaVM* pJVM, void** penv, jint version)
179 {
180 if (JNIVM.IsSupportedJNIVersion(version))
181 {
182 var env = JNIEnvContext.Current;
183 if (env != null)
184 {
185 *penv = env.pJNIEnv;
186 return JNIEnv.JNI_OK;
187 }
188
189 *penv = null;
190 return JNIEnv.JNI_EDETACHED;
191 }
192
193 *penv = null;
194 return JNIEnv.JNI_EVERSION;
195 }
196
197 internal static jint AttachCurrentThreadAsDaemon(JavaVM* pJVM, void** penv, void* args)
198 {
199 return AttachCurrentThreadImpl(pJVM, penv, (JavaVMAttachArgs*)args, true);
200 }
201
202 }
203
204#endif
205
206}
Implements the native mthods of 'java.lang.Thread'.
Definition Thread.cs:43
static unsafe int GetIndexOfNull(byte *ptr, int max=int.MaxValue)
Gets the length of a pointer to a C string.
Maintains a set of global refereces to instances.
Provides methods to assist in allocating memory for JNI.
Definition JNIMemory.cs:33
static nint Alloc(int cb)
Main state of the running JVM.
System.Int32 jint
Definition JavaVM.cs:35
delegate int pf_int_ppvoid_pvoid(JavaVM *pJVM, void **p1, void *p2)
static readonly MUTF8Encoding MUTF8
Definition JavaVM.cs:41
delegate int pf_int_ppvoid_int(JavaVM *pJVM, void **p1, int p2)
static Delegate[] vtableDelegates
Definition JavaVM.cs:50
delegate int pf_int(JavaVM *pJVM)