Skip to content

Instantly share code, notes, and snippets.

@ArhanChaudhary
Last active August 5, 2024 04:50
Show Gist options
  • Save ArhanChaudhary/20200eda359458aa72f748c285c139fd to your computer and use it in GitHub Desktop.
Save ArhanChaudhary/20200eda359458aa72f748c285c139fd to your computer and use it in GitHub Desktop.
Demonstrating how JNI makes true private state in Java impossible
# These commands are OS-dependent, this only works on Mac
javac Main.java -h .
gcc Main.c -o libSecret.dylib -shared -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin"
java Main
#include <jni.h>
#include "Main.h"
JNIEXPORT jobject JNICALL Java_Main_getSecret(JNIEnv *env, jobject obj, jobject secretObj)
{
jclass cls = (*env)->GetObjectClass(env, secretObj);
jfieldID field_id = (*env)->GetFieldID(env, cls, "secret", "Ljava/lang/Object;");
jobject secret = (*env)->GetObjectField(env, secretObj, field_id);
return secret;
}
public class Main {
static {
System.loadLibrary("Secret");
}
private native Object getSecret(Secret secret);
public static void main(String[] args) {
Secret secret = new Secret(Character.toString(65).repeat(10));
// "indirect access" as defined in my blog,
System.out.println(secret.get()) // outputs: AAAAAAAAA
// "direct access" as defined in my blog
System.out.println(new Main().getSecret(secret)); // also outputs: AAAAAAAAA
}
}
public class Secret {
private Object secret;
public Secret(Object secret) {
this.secret = secret;
}
public Object get() {
return secret;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment