IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
JNIFrame.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.Diagnostics;
26using System.Text;
27
28namespace IKVM.Runtime.JNI
29{
30
31 public unsafe struct JNIFrame
32 {
33
43 public static nint GetFuncPtr(object callerID, string clazz, string name, string sig)
44 {
45#if FIRST_PASS || IMPORTER || EXPORTER
46 throw new NotImplementedException();
47#else
48 var loader = RuntimeClassLoader.FromCallerID((ikvm.@internal.CallerID)callerID);
49 var argl = sizeof(nint) + sizeof(nint);
50 for (int i = 1; sig[i] != ')'; i++)
51 {
52 switch (sig[i])
53 {
54 case '[':
55 argl += sizeof(nint);
56 while (sig[++i] == '[') ;
57 if (sig[i] == 'L')
58 while (sig[++i] != ';') ;
59 break;
60 case 'L':
61 argl += sizeof(nint);
62 while (sig[++i] != ';') ;
63 break;
64 case 'J':
65 case 'D':
66 argl += 8;
67 break;
68 case 'F':
69 case 'I':
70 case 'C':
71 case 'Z':
72 case 'S':
73 case 'B':
74 argl += 4;
75 break;
76 default:
77 Debug.Assert(false);
78 break;
79 }
80 }
81
82 var mangledClass = JniMangle(clazz);
83 var mangledName = JniMangle(name);
84 var mangledSig = JniMangle(sig.Substring(1, sig.IndexOf(')') - 1));
85 var methodName = $"Java_{mangledClass}_{mangledName}";
86 var longMethodName = $"Java_{mangledClass}_{mangledName}__{mangledSig}";
87 JVM.Context.Diagnostics.GenericJniInfo($"Linking native method: {clazz}.{name}{sig}, classLoader = {loader}, methodName = {methodName}, longMethodName = {longMethodName}, argl = {argl}");
88
90 {
91 foreach (var p in loader.GetNativeLibraries())
92 {
93 if (LibJvm.Instance.JVM_FindLibraryEntry(p, NativeLibrary.MangleExportName(methodName, argl)) is nint h1 and not 0)
94 {
95 JVM.Context.Diagnostics.GenericJniInfo($"Native method {clazz}.{name}{sig} found in library 0x{p:X} (short)");
96 return h1;
97 }
98
99 if (LibJvm.Instance.JVM_FindLibraryEntry(p, NativeLibrary.MangleExportName(longMethodName, argl)) is nint h2 and not 0)
100 {
101 JVM.Context.Diagnostics.GenericJniInfo($"Native method {clazz}.{name}{sig} found in library 0x{p:X} (long)");
102 return h2;
103 }
104 }
105 }
106
107 var msg = $"{clazz}.{name}{sig}";
108 JVM.Context.Diagnostics.GenericJniError($"UnsatisfiedLinkError: {msg}");
109 throw new java.lang.UnsatisfiedLinkError(msg);
110#endif
111 }
112
113 static string JniMangle(string name)
114 {
115 var sb = new ValueStringBuilder(name.Length + 8);
116
117 foreach (var c in name)
118 {
119 switch (c)
120 {
121 case '/':
122 sb.Append('_');
123 break;
124 case '_':
125 sb.Append("_1");
126 break;
127 case ';':
128 sb.Append("_2");
129 break;
130 case '[':
131 sb.Append("_3");
132 break;
133 case >= '0' and <= '9':
134 case >= 'a' and <= 'z':
135 case >= 'A' and <= 'Z':
136 sb.Append(c);
137 break;
138 default:
139 sb.Append($"_0{(int)c:x4}");
140 break;
141 }
142 }
143
144 return sb.ToString();
145 }
146
147#if FIRST_PASS || IMPORTER || EXPORTER
148#else
149
150 JNIEnvContext env;
151 JNIEnvContext.FrameState prevFrameState;
152
153#endif
154
160 internal RuntimeClassLoader Enter(RuntimeClassLoader loader)
161 {
162#if FIRST_PASS || IMPORTER || EXPORTER
163 throw new NotImplementedException();
164#else
165 Enter((object)null);
166
167 var prev = env.classLoader;
168 env.classLoader = loader;
169 return prev;
170#endif
171 }
172
176 internal readonly void Leave(RuntimeClassLoader prev)
177 {
178#if FIRST_PASS || IMPORTER || EXPORTER
179 throw new NotImplementedException();
180#else
181 env.classLoader = prev;
182 Leave();
183#endif
184 }
185
191 public nint Enter(object callerID)
192 {
193#if FIRST_PASS || IMPORTER || EXPORTER
194 throw new NotImplementedException();
195#else
196 env = JNIEnvContext.Current ?? JNIEnv.CreateJNIEnv(JVM.Context)->GetContext();
197 prevFrameState = env.Enter((ikvm.@internal.CallerID)callerID);
198 return (nint)(void*)env.pJNIEnv;
199#endif
200 }
201
205 public readonly void Leave()
206 {
207#if FIRST_PASS || IMPORTER || EXPORTER
208 throw new NotImplementedException();
209#else
210 env.Leave(prevFrameState);
211 JVM.ThrowPendingException();
212#endif
213 }
214
215 public readonly nint MakeLocalRef(object obj)
216 {
217#if FIRST_PASS || IMPORTER || EXPORTER
218 throw new NotImplementedException();
219#else
220 return env.MakeLocalRef(obj);
221#endif
222 }
223
224 public readonly object UnwrapLocalRef(nint p)
225 {
226#if FIRST_PASS || IMPORTER || EXPORTER
227 throw new NotImplementedException();
228#else
229 return JNIEnv.UnwrapRef(env, p);
230#endif
231 }
232
233 }
234
235}
static readonly object SyncRoot
Main state of the running JVM.
Provides methods to load libraries from standard .NET search locations. This class is not used to loa...
Runtime support for a class loader.
IDiagnosticHandler Diagnostics
Gets the IDiagnosticHandler where events should be sent.
void GenericJniError(string arg0)
The 'GenericJniError' diagnostic.
void GenericJniInfo(string arg0)
The 'GenericJniInfo' diagnostic.
static nint GetFuncPtr(object callerID, string clazz, string name, string sig)
Invoked by managed code to acquire a function pointer to a native JNI method.
Definition JNIFrame.cs:43
readonly object UnwrapLocalRef(nint p)
Definition JNIFrame.cs:224
readonly void Leave()
Leaves a JNIFrame previously entered.
Definition JNIFrame.cs:205
readonly nint MakeLocalRef(object obj)
Definition JNIFrame.cs:215
JNIEnvContext.FrameState prevFrameState
Definition JNIFrame.cs:151
nint Enter(object callerID)
Enters the JNIFrame with a specified ikvm.@internal.CallerID in scope.
Definition JNIFrame.cs:191
static string JniMangle(string name)
Definition JNIFrame.cs:113