Skip to content

Latest commit

 

History

History
151 lines (120 loc) · 4.5 KB

README.md

File metadata and controls

151 lines (120 loc) · 4.5 KB

Overlord

Opus #1

A powerful memory management library.

Perform illegal, unsafe and incredibly dangerous operations on your JVM's native memory with no restrictions.

You can also pretend this is C, and manage memory directly! :)

Features:

  • Create objects without using their constructor.
  • Edit objects in heap memory.
  • Assign and manage memory outside of the heap.
  • Store objects and data outside of the heap.
  • Edit intrinsic parts of an object, such as headers, klass pointers, mark words, etc.
  • Transform objects to an incompatible type at runtime.
  • Cast objects to incompatible types.
  • Create shallow and deep perfect clones of objects.
  • Construct objects using the constructor from a completely unrelated class.
  • Trace where methods are called.
  • Use real objects to provide the implementation for native methods.
  • Load classes at runtime, both hidden and explicitly.
  • Create pointers to objects in memory.
  • Rewrite the behaviour of a method at runtime for reflective access.
  • Break encapsulation and open jdk.internal classes for access.
  • Silence those pesky "illegal reflection" warnings.

Maven Information

<repository>
    <id>pan-repo</id>
    <name>Pandaemonium Repository</name>
    <url>https://gitlab.com/api/v4/projects/18568066/packages/maven</url>
</repository>
<dependency>
    <groupId>mx.kenzie</groupId>
    <artifactId>overlord</artifactId>
    <version>1.0.1</version>
    <scope>compile</scope>
</dependency>

Examples

Shallow-clone an object (creates a NEW instance, but any non-primitive field will be a reference to the original.)

final MyObject original = new MyObject();
final MyObject clone = Overlord.shallowClone(source);

assert original.objectField == clone.objectField;

Deep-clone an object (creates a NEW instance, any non-primitive non-constant field will be recursively deep-cloned from the original.)

final MyObject original = new MyObject();
final MyObject clone = Overlord.deepClone(source);

assert original.objectField != clone.objectField;

With the following class structure:

static class NativeImplClass {
    public native String getWord();
    public native void setWord(String word);
    public native int getNumber();
    public native void setNumber(int number);
}

static class RealClass {
    int number = 10;
    String word = "hello";

    protected String getWord() { return word; }
    protected void setWord(String word) { this.word = word; }
    protected int getNumber() { return number; }
    protected void setNumber(int number) { this.number = number; }
}

You can use NativeImplClass as a blind implementation in the following:

final RealClass original = new RealClass();
final NativeImplClass cast = Overlord.transform(original, NativeImplClass.class); // Transforms 'original' to an instance of NativeImplClass
// the 'cast' variable is strongly-typed and so valid hereafter
Overlord.transform(original, RealClass.class); // Transforms 'original' back to its true class
// Now any methods called will be executed on RealClass

cast.setNumber(10); // The compiler will execute this public method from NativeImplClass
                    // The JVM will *actually* execute the protected getNumber method from RealClass

Swapping a constructor:

static class Class2 {
    public final int number;
    public final String name;

    public Class2(String string) {
        number = 10;
        name = string;
    }

}

static class Class1 {
    public final int number;
    public final String name;

    public Class1(String string) {
        number = 5;
        name = string + " <- thing";
    }

}

Any fields set in the copy constructor will either target the object's fields or be ignored silently.

final Class1 class1 = Overlord.createSwapConstructor(Class1.class, Class2.class, "hello");

assert class1.number == 10;
assert class1.name.equalsIgnoreCase("hello");

Creating an empty object:

final Class1 obj = Overlord.createEmpty(Class1.class);

Replacing method behaviour for reflection access:

{
    Method method = Blob.class.getMethod("myMethod");
    Overlord.setReflectiveBehaviour(method, (obj, args) -> "please don't use reflection on me!");
}


Method method = Blob.class.getMethod("myMethod");

// method.invoke(new Blob()) == "please don't use reflection on me!"
// new Blob().myMethod() == whatever the original was

assert !method.invoke(new Blob()).equals(new Blob().myMethod());

See RewriteBehaviourTest.class for more examples.