Accessing the sid through an ACLEntry without Reflection

235 Views Asked by At

We are working on an application in which we need to pass a SID.

We have an ACLEntry object from which we obtain the UserPrincipal then using reflection, we make the sid field accessible and retrieve it.

    //reflection to get sid string, so we can return sid with userAndGroup name
    Class<?> c = Class.forName("sun.nio.fs.WindowsUserPrincipals$User");
    Field sidString = c.getDeclaredField("sidString");
    sidString.setAccessible(true);
    UserPrincipal userPrincipal = aclEntry.principal();
    String sid = ((String) sidString.get(userPrincipal)).toLowerCase();

This worked on Java 8 but we're migrating to Java 17 and when we run the code, we receive the error: java.lang.reflect.InaccessibleObjectException: Unable to make field private final java.lang.String sun.nio.fs.WindowsUserPrincipals$User.sidString accessible: module java.base does not "opens sun.nio.fs" to unnamed module @5f150435

Is there a way to access this sidString without using reflection or is there a way to bypass this InaccessibleObjectException using reflection?

2

There are 2 best solutions below

0
Paul Curran On

It looks like this has already been answered.

We added the following to the VM Arguments and the reflection code worked.

 --add-opens has the following syntax: {A}/{package}={B}
java --add-opens java.base/java.lang=ALL-UNNAMED

To add it to the VM Arguments automatically, we updated pom file. : https://stackoverflow.com/questions/70196098/how-can-i-specify-add-opens-from-a-project-level-and-make-sure-it-is-taken-int

Then for the : https://maven.apache.org/plugins/maven-shade-plugin/examples/executable-jar.html

5
violet945786 On

You can pass your field in to this to force it to be accessible:

public static <T extends AccessibleObject> T forceAccessible(T o) { //code taken from https://github.com/TheOneAndOnlyDanSan/Reflection
    try {
        Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
        unsafeField.setAccessible(true);
        Unsafe unsafe = (Unsafe) unsafeField.get(null);

        Method m = Class.class.getDeclaredMethod("getDeclaredFields0", boolean.class);
        m.setAccessible(true);
        Field override = ((Field[]) m.invoke(AccessibleObject.class, false))[0];
        unsafe.putBoolean(override, unsafe.objectFieldOffset(override), true);

        if (!override.getBoolean(o)) {
            try {
                o.setAccessible(true);
            } catch (InaccessibleObjectException e) {
                unsafe.putBoolean(o, unsafe.objectFieldOffset(override), true);
            }
        }
    } catch (Exception e) {}
    return o;
}

edit: replaced deprecated "o.isAccessible()" with "!override.getBoolean(o)" and added "unsafe.putBoolean(override, unsafe.objectFieldOffset(override), true);"