Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

Permit Reflection

utilities for working with java 11 (and 12) modules

  • Permit.setAccessible enables access for a Field or Method without regard for modules
  • Permit.godMode opens all packages in all modules to all modules
  • Permit.main runs a specified class's main method in god mode. this should allow many java 8 programs to run with later versions of java
  • is a fluent api for semi-typesafe access to unsafe

in summary, it bypasses most of the runtime module checks put in place by project jigsaw and the JPMS

see the demo and pshell directories for some usage examples




using Permit.main to run another classes main method in god mode, eg from the demo directory run:

JAVA_HOME=$java11 mvn clean package exec:java -Dexec.mainClass=com.nqzero.permit.Permit \
        -Dexec.args="demo.DemoNormal --class-path target/classes"

a RAF file descriptor is private, but this works (and Field.setAccessible doesn't):

        FileDescriptor fd = new RandomAccessFile("/etc/hosts","r").getFD();
        Field field = FileDescriptor.class.getDeclaredField("fd");

a fluent, semi-typesafe api for unsafe:

        ClassLoader cl = new Object() {}.getClass().getClassLoader();
        Permit<ClassLoader,String> app = build(cl,"ucp")
        String path =;

access the JShell directly

  • god mode fixes Field.setAccessible at runtime
  • compile with java 8 source and target (to bypass compile-time checks)
  • full source is in the pshell directory
  • JAVA_HOME=$java11 mvn package exec:java -Dexec.mainClass=demo.Pshell
  • wait 4 seconds after jshell starts ... will print "hello world" and foobar will be defined
  • these are injected from a separate thread after jshell is started

        jdk.internal.jshell.tool.JShellTool tool
                = new jdk.internal.jshell.tool.JShellToolBuilder().rawTool();
        Field field = tool.getClass().getDeclaredField("state");

        // inject some values into the shell
        new Thread(() -> { try {

            JShell jshell = (JShell) field.get(tool);
            jshell.eval("String foobar = \"hello world\";");

        } catch (Exception ex) {} }).start();

        tool.start(new String[0]);        

a word about security

nothing about this library makes java less secure

  • when running with a security manager, Permit fails
  • code running without this library can access your home directory, the network, etc
  • this library breaks encapsulation, not security

the freedom to tinker

part of what makes java free is the ability to use apis in a manner not anticipated by the companies that produce them. project jigsaw undermines this freedom. help keep the freedom in java by exercising reflection !


  • all files in this repo copyright 2018 nqzero, and are offered under the terms of the MIT License
  • the build targets java 6, but must be built with at least java 9 (needs Module.class and etc)
  • should run on java 7, java 8, java 9, java 10, java 11, and java 12
  • features not available on a given platform, eg god mode on java 8, should degrade gracefully
  • using javac -source 1.8 -target 1.8 bypasses the compile-time checks


starting with java 9, most reflection is considered "illegal". eg, running demo.DemoNormal without a security manager you'll get the following warning and exception:

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by demo.DemoNormal
         (file:/.../permit-reflect/demo/target/classes/) to field
WARNING: Please consider reporting this to the maintainers of demo.DemoNormal
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

Exception in thread "main" java.lang.IllegalAccessError:
    class demo.DemoNormal (in unnamed module @0xb065c63)
    cannot access class jdk.internal.jshell.tool.JShellToolBuilder (in module jdk.jshell)
    because module jdk.jshell does not export jdk.internal.jshell.tool to unnamed module @0xb065c63
    at demo.DemoNormal.main(

this was access that was fine with java 8 and earlier

modules can also prevent compiling code with java 11 (or 9 or 10), eg:

src/demo/ error: package jdk.internal.jshell.tool is not visible
        jdk.internal.jshell.tool.JShellTool tool
  (package jdk.internal.jshell.tool is declared in module jdk.jshell, which does not export it)

a developer can work around these problems with --add-exports or by compiling with java 8. permit-reflect can't help with these compilation issues


permit reflective access for java 11







No releases published


No packages published