2323 */
2424package com .sun .jna ;
2525
26+ import com .sun .jna .Callback .UncaughtExceptionHandler ;
27+ import com .sun .jna .Structure .FFIType ;
2628import java .awt .Component ;
2729import java .awt .GraphicsEnvironment ;
2830import java .awt .HeadlessException ;
3335import java .io .IOException ;
3436import java .io .InputStream ;
3537import java .io .UnsupportedEncodingException ;
38+ import java .lang .invoke .MethodHandle ;
39+ import java .lang .invoke .MethodHandles ;
40+ import java .lang .invoke .MethodHandles .Lookup ;
41+ import java .lang .invoke .MethodType ;
3642import java .lang .ref .Reference ;
3743import java .lang .ref .WeakReference ;
3844import java .lang .reflect .Array ;
5056import java .nio .charset .Charset ;
5157import java .nio .charset .IllegalCharsetNameException ;
5258import java .nio .charset .UnsupportedCharsetException ;
53- import java .security .AccessController ;
5459import java .security .PrivilegedAction ;
5560import java .util .ArrayList ;
5661import java .util .Arrays ;
6065import java .util .Map ;
6166import java .util .StringTokenizer ;
6267import java .util .WeakHashMap ;
63-
64- import com .sun .jna .Callback .UncaughtExceptionHandler ;
65- import com .sun .jna .Structure .FFIType ;
6668import java .util .logging .Level ;
6769import java .util .logging .Logger ;
70+ import java .util .stream .Stream ;
6871
6972/** Provides generation of invocation plumbing for a defined native
7073 * library interface. Also provides various utilities for native operations.
@@ -181,6 +184,16 @@ public void uncaughtException(Callback c, Throwable e) {
181184 private static final int TYPE_BOOL = 4 ;
182185 private static final int TYPE_LONG_DOUBLE = 5 ;
183186
187+ private static final MethodHandle stackWalkerGetInstance ;
188+ private static final Enum stackWalkerRetainClassReference ;
189+ private static final MethodHandle stackWalkerWalk ;
190+ private static final Object stackWalkerFilter ;
191+
192+ private static final MethodHandle securityManagerExposerConstructor ;
193+ private static final MethodHandle securityManagerGetClassContext ;
194+
195+ private static final MethodHandle accessControllerDoPrivileged ;
196+
184197 static final int MAX_ALIGNMENT ;
185198 static final int MAX_PADDING ;
186199
@@ -255,6 +268,70 @@ static boolean isCompatibleVersion(String expectedVersion, String nativeVersion)
255268 || (Platform .isAndroid () && !Platform .isIntel ())
256269 ? 8 : LONG_SIZE ;
257270 MAX_PADDING = (Platform .isMac () && Platform .isPPC ()) ? 8 : MAX_ALIGNMENT ;
271+
272+ Enum stackWalkerRetainClassReferenceBuilder ;
273+ MethodHandle stackWalkerGetInstanceBuilder ;
274+ MethodHandle stackWalkerWalkBuilder ;
275+ Object stackWalkerFilterBuilder ;
276+ try {
277+ Lookup lookup = MethodHandles .lookup ();
278+ Class <?> stackWalkerClass = Class .forName ("java.lang.StackWalker" );
279+ Class <? extends Enum > stackWalkerOptionClass = (Class <? extends Enum >) Class .forName ("java.lang.StackWalker$Option" );
280+ stackWalkerRetainClassReferenceBuilder = Enum .valueOf (stackWalkerOptionClass , "RETAIN_CLASS_REFERENCE" );
281+ stackWalkerGetInstanceBuilder = lookup .findStatic (stackWalkerClass , "getInstance" , MethodType .methodType (stackWalkerClass , stackWalkerOptionClass ));
282+ stackWalkerWalkBuilder = lookup .findVirtual (stackWalkerClass , "walk" , MethodType .methodType (Object .class , java .util .function .Function .class ));
283+ Class <?> stackframe = Class .forName ("java.lang.StackWalker$StackFrame" );
284+ MethodHandle stackFrameGetDeclaringClass = lookup .findVirtual (stackframe , "getDeclaringClass" , MethodType .methodType (Class .class ));
285+ stackWalkerFilterBuilder = new java .util .function .Function <Stream <Object >, Class <?>>() {
286+ @ Override
287+ public Class <?> apply (Stream <Object > t ) {
288+ Object stackFrame = t .skip (2 ).findFirst ().get ();
289+ try {
290+ return (Class <?>) stackFrameGetDeclaringClass .invoke (stackFrame );
291+ } catch (Throwable ex ) {
292+ return null ;
293+ }
294+ }
295+ };
296+
297+ } catch (Throwable ex ) {
298+ LOG .log (Level .FINE , "Failed to initialize stack accessor method StackWalker" , ex );
299+ stackWalkerRetainClassReferenceBuilder = null ;
300+ stackWalkerGetInstanceBuilder = null ;
301+ stackWalkerWalkBuilder = null ;
302+ stackWalkerFilterBuilder = null ;
303+ }
304+ stackWalkerRetainClassReference = stackWalkerRetainClassReferenceBuilder ;
305+ stackWalkerGetInstance = stackWalkerGetInstanceBuilder ;
306+ stackWalkerWalk = stackWalkerWalkBuilder ;
307+ stackWalkerFilter = stackWalkerFilterBuilder ;
308+
309+ MethodHandle securityManagerExposerConstructorBuilder ;
310+ MethodHandle securityManagerGetClassContextBuilder ;
311+ try {
312+ Lookup lookup = MethodHandles .lookup ();
313+ Class <?> securityManagerExposerClass = Class .forName ("com.sun.jna.SecurityManagerExposer" );
314+ securityManagerExposerConstructorBuilder = lookup .findConstructor (securityManagerExposerClass , MethodType .methodType (void .class ));
315+ securityManagerGetClassContextBuilder = lookup .findVirtual (securityManagerExposerClass , "getClassContext" , MethodType .methodType (Class [].class ));
316+ } catch (Throwable ex ) {
317+ LOG .log (Level .FINE , "Failed to initialize stack accessor method SecurityManager" , ex );
318+ securityManagerExposerConstructorBuilder = null ;
319+ securityManagerGetClassContextBuilder = null ;
320+ }
321+ securityManagerExposerConstructor = securityManagerExposerConstructorBuilder ;
322+ securityManagerGetClassContext = securityManagerGetClassContextBuilder ;
323+
324+ MethodHandle accessControllerDoPrivilegedBuilder = null ;
325+ try {
326+ Lookup lookup = MethodHandles .lookup ();
327+ Class <?> accessControllerClass = Class .forName ("java.security.AccessController" );
328+ accessControllerDoPrivilegedBuilder = lookup .findStatic (accessControllerClass , "doPrivileged" , MethodType .methodType (Object .class , PrivilegedAction .class ));
329+ } catch (Throwable ex ) {
330+ LOG .log (Level .FINE , "Failed to initialize AccessController#doPrivileged" , ex );
331+ accessControllerDoPrivilegedBuilder = null ;
332+ }
333+ accessControllerDoPrivileged = accessControllerDoPrivilegedBuilder ;
334+
258335 System .setProperty ("jna.loaded" , "true" );
259336 }
260337
@@ -1275,7 +1352,7 @@ public static String getWebStartLibraryPath(final String libName) {
12751352 try {
12761353
12771354 final ClassLoader cl = Native .class .getClassLoader ();
1278- Method m = AccessController . doPrivileged (new PrivilegedAction <Method >() {
1355+ Method m = ( Method ) accessControllerDoPrivileged . invoke (new PrivilegedAction <Method >() {
12791356 @ Override
12801357 public Method run () {
12811358 try {
@@ -1294,7 +1371,7 @@ public Method run() {
12941371 }
12951372 return null ;
12961373 }
1297- catch (Exception e ) {
1374+ catch (Throwable e ) {
12981375 return null ;
12991376 }
13001377 }
@@ -1523,19 +1600,35 @@ static Class<?> findDirectMappedClass(Class<?> cls) {
15231600 was made.
15241601 */
15251602 static Class <?> getCallingClass () {
1526- Class <?>[] context = new SecurityManager () {
1527- @ Override
1528- public Class <?>[] getClassContext () {
1529- return super .getClassContext ();
1603+ if (stackWalkerGetInstance != null ) {
1604+ try {
1605+ Object walker = stackWalkerGetInstance .invoke (stackWalkerRetainClassReference );
1606+ Class <?> caller = (Class <?>) stackWalkerWalk .invoke (walker , stackWalkerFilter );
1607+ return caller ;
1608+ } catch (Throwable ex ) {
1609+ LOG .log (Level .WARNING , "Failed to invoke StackWalker#getInstance or StackWalker#walk" , ex );
15301610 }
1531- }.getClassContext ();
1532- if (context == null ) {
1533- throw new IllegalStateException ("The SecurityManager implementation on this platform is broken; you must explicitly provide the class to register" );
15341611 }
1535- if (context .length < 4 ) {
1536- throw new IllegalStateException ("This method must be called from the static initializer of a class" );
1612+
1613+ if (securityManagerExposerConstructor != null ) {
1614+ Class <?>[] context = null ;
1615+ try {
1616+ Object securityManagerExposer = securityManagerExposerConstructor .invoke ();
1617+ context = (Class <?>[]) securityManagerGetClassContext .invoke (securityManagerExposer );
1618+ } catch (Throwable ex ) {
1619+ LOG .log (Level .WARNING , "Failed to invoke SecurityManagerExposer#<init> or SecurityManagerExposer#getClassContext" , ex );
1620+ }
1621+
1622+ if (context == null ) {
1623+ throw new IllegalStateException ("The SecurityManager implementation on this platform is broken; you must explicitly provide the class to register" );
1624+ }
1625+ if (context .length < 4 ) {
1626+ throw new IllegalStateException ("This method must be called from the static initializer of a class" );
1627+ }
1628+ return context [3 ];
15371629 }
1538- return context [3 ];
1630+
1631+ throw new IllegalStateException ("Neither the StackWalker, nor the SecurityManager based getCallingClass implementation are useable; you must explicitly provide the class to register" );
15391632 }
15401633
15411634 /**
0 commit comments