Last active
January 11, 2020 21:52
-
-
Save raphw/be0994259e75652f057c9e1d3ee5f567 to your computer and use it in GitHub Desktop.
Example of a shadingproof JNI binding.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.shadeproof; | |
import net.bytebuddy.ByteBuddy; | |
public abstract class NativeBinding { | |
public static final NativeBinding INSTANCE; | |
static { | |
System.load("mylibrary"); | |
String expected = "!com!shadeproof!NativeBinding!"; | |
expected = expected.substring(1, expected.length() - 1).replace('!', '.'); | |
if (NativeBinding.class.getName().equals(expected)) { | |
INSTANCE = new DirectNativeBinding(); | |
} else { | |
try { | |
INSTANCE = new ByteBuddy() | |
.redefine(DirectNativeBinding.class) | |
.name(expected) | |
.make() | |
.load(NativeBinding.class.getClassLoader(), ClassLoadingStrategy.Default.INJECTION) | |
.getLoaded() | |
.getConstructor() | |
.newInstance(); | |
} catch (Exception e) { | |
throw new IllegalStateException(e); | |
} | |
} | |
} | |
public abstract void method(); | |
private static class DirectNativeBinding extends NativeBinding { | |
public native void method(); | |
} | |
} |
Lacks ClassLoadingStrategy.Default.INJECTION
, loading native code only works for the same class loader, the hierarchy is not applied for those.
ClassLoadingStrategy.Default.INJECTION
does not work if the target class loader contains a non-shaded version as well as a shaded version, therefore ClassLoadingStrategy.Default.CHILD_FIRST
seems more appropriate. To make sure the native library is loaded from the child class loader, it should be loaded form the static initializer of the DirectNativeBinding
class. See also https://gist.github.com/felixbarny/3f519ac49520018aa8ecc82cae352670
Indeed, have not considered that case. Thanks for the hint, I'll keep it in the back in my head if I run into that.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Seems like a pretty neat trick! However, I can't make it to work. I've tried it with the async-profiler Java API but had no luck. This is a minimal example:
But unfortunately, I still get an UnsatisfiedLinkError
Do you have any clue what I could have done wrong? When not shading it and instantiating normally it works as expected. I've tried with JDK 11.0.2.