Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REPO: Replace current metadata solution with a bytecode generated subclass in a classloader solution #9

Open
jasonewall opened this issue Dec 21, 2014 · 0 comments

Comments

@jasonewall
Copy link
Owner

Here is a really basic example using Javassist as the bytecode generator.

import ca.thejayvm.playground.java8.Person;
import javassist.*;

import java.lang.reflect.Modifier;

/**
 * Created by jason on 14-11-16.
 */
public class JavassistMain {
    public static void main(String[] args) throws NotFoundException, CannotCompileException, IllegalAccessException, InstantiationException {
        Class<? extends Person> personMetaClass = createClass();
        Person peep = personMetaClass.newInstance();
        peep.setFirstName("Jason");
        peep.setLastName("Wall");
        System.out.println(peep.getFirstName());
        InvocationTracker tracker = (InvocationTracker)peep;
        tracker.getInvocations().forEach(System.out::println);
    }

    @SuppressWarnings("unchecked")
    public static Class<? extends Person> createClass() throws NotFoundException, CannotCompileException {
        return getCtClass().toClass();
    }

    private static CtClass getCtClass() throws NotFoundException, CannotCompileException {
        ClassPool pool = ClassPool.getDefault();
        CtClass list = pool.get(java.util.List.class.getName());
        CtClass invocationTracker = pool.get(InvocationTracker.class.getName());
        CtClass subClass = pool.makeClass(Person.class.getName() + "Meta");
        final CtClass superClass = pool.get(Person.class.getName());
        subClass.setSuperclass(superClass);
        subClass.setInterfaces(new CtClass[]{ invocationTracker });
        subClass.setModifiers(Modifier.PUBLIC);

        CtField invocations = CtField.make("public java.util.List invocations = new java.util.ArrayList();", subClass);
        subClass.addField(invocations);

        CtMethod getInvocations = CtNewMethod.make(list, "getInvocations", new CtClass[]{}, new CtClass[]{}, "{ return invocations; }", subClass);
        subClass.addMethod(getInvocations);

        CtMethod setFirstName = CtNewMethod.make("public void setFirstName(String s) { invocations.add(\"firstName\"); super.setFirstName(s); }", subClass);
        subClass.addMethod(setFirstName);
        return subClass;
    }
}

The Metadata classloader also needs to be a child of the hex ClassLoader layer. It also needs to be cached at that level so it probably cannot be a singleton. An individual application will probably be responsible for declaring and storing its own metadata cache.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant