4

Below function Hacks the "HttpURLConnection#methods" static field (through Java Reflection). I am using reflection to unit test my code functionality. I found out we can not change the static final fields in JDK12. I found one solution to use unsafe but I am not sure how can I get this function working in JDK12 using unsafe.

protected static void allowMethods(String... methods) {
    try {
        Field methodsField = HttpURLConnection.class.getDeclaredField("methods");

        Field modifiersField = Unsafe.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.setInt(methodsField, methodsField.getModifiers() & ~Modifier.FINAL);

        methodsField.setAccessible(true);

        String[] oldMethods = (String[]) methodsField.get(null);
        Set<String> methodsSet = new LinkedHashSet<>(Arrays.asList(oldMethods));
        methodsSet.addAll(Arrays.asList(methods));
        String[] newMethods = methodsSet.toArray(new String[0]);

        methodsField.set(null/*static field*/, newMethods);
    } catch (NoSuchFieldException | IllegalAccessException e) {
        throw new IllegalStateException(e);
    }
}  

This is the stacktrace for the above code:

Caused by: java.lang.IllegalStateException: java.lang.NoSuchFieldException: modifiers
at pii.rest.call.RestUtils.allowMethods(RestUtils.java:75)
at pii.rest.call.JobAbort.<clinit>(JobAbort.java:39)
Caused by: java.lang.NoSuchFieldException: modifiers
at java.base/java.lang.Class.getDeclaredField(Class.java:2549)
at pii.rest.call.RestUtils.allowMethods(RestUtils.java:62)

Can anybody help me convert this function to use Unsafe so therefore it works with JDK12+. I have tried this until now:

final Field ourField = HttpURLConnection.class.getDeclaredField("methods");
final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
final Unsafe unsafe = (Unsafe) unsafeField.get(null);
final Object staticFieldBase = unsafe.staticFieldBase(ourField);
final long staticFieldOffset = unsafe.staticFieldOffset(ourField);
unsafe.putObject(staticFieldBase, staticFieldOffset, "it works");
Johannes Kuhn
  • 14,778
  • 4
  • 49
  • 73
Mutahir Kiani
  • 83
  • 1
  • 1
  • 11
  • 4
    Possible duplicate: https://stackoverflow.com/questions/56039341/get-declared-fields-of-java-lang-reflect-fields-in-jdk12/56043252 – Slaw Sep 09 '21 at 21:54
  • 3
    Does this answer your question? [Get declared fields of java.lang.reflect.Fields in jdk12](https://stackoverflow.com/questions/56039341/get-declared-fields-of-java-lang-reflect-fields-in-jdk12) – yu.pitomets Sep 09 '21 at 22:28
  • 1
    This is clearly wrong: `Unsafe.class.getDeclaredField("modifiers");` The `Unsafe` class doesn't have a `modifiers` field. – Stephen C Sep 10 '21 at 00:02
  • 2
    What actual goal do you want to achieve? Make `HttpURLConnection` accept a non-standard method? That can be done be easier by setting the instance field `method` of an actual `HttpURLConnection` instance, bypassing the check. Unlike `static final` fields, instance fields can be set with a simple `setAccessible(true)` without manipulating the `Field` internals, of course, assuming that you’re either in the unnamed module or have specified the necessary `--add-opens` option. – Holger Sep 10 '21 at 11:57
  • HTTPURLConnection does not support PATCH call. That is why I used this hack to to use reflection to hack the HttpURLConnection#methods static field (through Java Reflection) to add support for "PATCH" (which is not supported by default). – Mutahir Kiani Sep 10 '21 at 13:52
  • This hack works until JDK11 but JDK12+ giving the error mentioned in the question – Mutahir Kiani Sep 10 '21 at 13:57
  • 2
    Given Java 11 is still supported, but Java 12 has been out of support since September 2019, why are you upgrading to Java 12? If anything, try to target Java 16 (current supported version) or Java 17 (next LTS to be released later this month). – Mark Rotteveel Sep 11 '21 at 10:55
  • Thank you, this problem also exist in Java16 but yesterday I was manage to solve in Java12+ by using VarHandles. – Mutahir Kiani Sep 12 '21 at 11:03

0 Answers0