Skip to content

CShared

Lenni0451 edited this page Mar 17, 2024 · 1 revision

The CShared annotation allows for sharing variables between multiple transformer methods injecting into the same target method.
The value field specifies the name of the shared variable. It is used to identify the variables in the transformer methods.

Shared variables are initialized with the default value of the type of the variable (0 for numbers, false for booleans and null for objects).
Unlike local variables using the CLocalVariable annotation, shared variables are always modifiable.

By default, the shared variables are only accessible in all methods of the same transformer but can be made global by setting the global field to true.
When accessing a global shared variable, the global field has to be set to true as well.

Example

Sharing a variable inside a transformer:

@CTransformer(TestClass.class)
public class Transformer1 {
    @CInject(method = "test", target = @CTarget("HEAD"))
    public void method1(@CShared("shared") String s) {
        s = "Hello World!";
    }

    @CInject(method = "test", target = @CTarget("RETURN"))
    public void method2(@CShared("shared") String s) {
        System.out.println(s); //Prints "Hello World!"
    }

    //The variable is not accessible in this method because of global being true
    @CInject(method = "test", target = @CTarget("RETURN"))
    public void method3(@CShared(value = "shared", global = true) String s) {
        System.out.println(s); //Prints null
    }
}

//The variable is not shared between different transformers
@CTransformer(TestClass.class)
public class Transformer2 {
    @CInject(method = "test", target = @CTarget("RETURN"))
    public void method(@CShared("shared") String s) {
        System.out.println(s); //Prints null
    }
}

Sharing a variable between transformers:

@CTransformer(TestClass.class)
public class Transformer1 {
    @CInject(method = "test", target = @CTarget("HEAD"))
    public void method1(@CShared(value = "shared", global = true) String s) {
        s = "Hello World!";
    }

    @CInject(method = "test", target = @CTarget("RETURN"))
    public void method2(@CShared(value = "shared", global = true) String s) {
        System.out.println(s); //Prints "Hello World!"
    }

    //The variable is not accessible in this method because of global being false
    @CInject(method = "test", target = @CTarget("RETURN"))
    public void method3(@CShared("shared") String s) {
        System.out.println(s); //Prints null
    }
}

@CTransformer(TestClass.class)
public class Transformer2 {
    @CInject(method = "test", target = @CTarget("RETURN"))
    public void method(@CShared(value = "shared", global = true) String s) {
        System.out.println(s); //Prints "Hello World!"
    }
}

Injected code

Original method:

public String method(final String arg) {
    return "hello " + arg;
}

Transformer method:

@CInject(method = "method", target = @CTarget("HEAD"))
public void method1(@CShared("shared") String s) {
    //Your IDE may complain about the variable not being used
    s = "Hello World!";
}

@CInject(method = "method", target = @CTarget("RETURN"))
public void method2(@CShared("shared") String s) {
    System.out.println(s);
}

Injected code:

public String method(final String arg) {
    //Shared variables are initialized at the start of the method
    String shared = null;

    //Create an array to pass the shared variables to the transformer method
    Object[] sharedVariables = new Object[1];
    sharedVariables[0] = shared; //Set the variable in the array
    method1(sharedVariables); //Call the transformer method
    shared = (String) sharedVariables[0]; //Set the value back to the shared variable

    String s = "hello " + arg; //The original code of the method

    //Same call code as above
    sharedVariables = new Object[1];
    sharedVariables[0] = shared;
    method2(sharedVariables);
    shared = (String) sharedVariables[0];

    return s; //The original code of the method
}

//ClassTransform automatically remapped the transformer method to use an Object[]
public void method1(Object[] sharedVariables) {
    sharedVariables[0] = "Hello World!";
}

public void method2(Object[] sharedVariables) {
    System.out.println(sharedVariables[0]);
}

Clone this wiki locally