I tried metaprogramming in Java

Introduction

Using a metaprogramming library called javassist I tried to rewrite the class that I actually created.

You can use it when you are using the library and think it's shit. (Mysterious log is output, etc ...)

Import library

I'm using gradle.

build.gradle


...
dependencies {
...
    compile group: 'org.javassist', name: 'javassist', version: '3.15.0-GA'
}

Actually rewrite

Actually rewrite the prepared class called User, Add a field called money.

data/User.java


package data;

public class User {
    private String name;

    private int age;

    private float height;
    private float width;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public String getUserInfo() {
        return "name: " + name + ", age: " + age;
    }
}

Main.java


import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtMethod;
import javassist.Modifier;

public class Test {
    public static void main(String[] args) {
        try {
            //Get the pool for all classes.
            ClassPool pool = ClassPool.getDefault();

            //Full data of package name and class name.Search for User
            //If not found, an exception will be thrown.
            CtClass ctc = pool.get("data.User");

            //Specify the field type, field name, and declaration destination as arguments.
            CtField field = new CtField(CtClass.intType, "money", ctc);

            //Specify field qualifier
            //If there are multiple modifiers|I will add it with.
            // field.setModifiers(Modifier.STATIC | Modifier.PRIVATE);
            field.setModifiers(Modifier.PRIVATE);

            //Add field.
            ctc.addField(field);

            //Get the defined method.
            CtMethod method = ctc.getDeclaredMethod("getUserInfo");
            //Changed to output money by replacing the inside of the method.
            method.setBody("return \"name: \" + name + \", age: \" + age + \", money: \" + money;");

            //Overwrite class in class loader.
            Class cls = ctc.toClass(ClassLoader.getSystemClassLoader(), AsmTest.class.getProtectionDomain());

            //Instantiate a class with reflection.
            User ins = (User) cls.newInstance();
            ins.setName("Bob");//Specify Bob for name.

            //Since money is added after compilation, get it by reflection.
            Field f = cls.getDeclaredField("money");

            //Changed accessibility.
            //If private or protected, set it to true so that it can be accessed.
            f.setAccessible(true);

            //Change the money field to 1500 with int.
            f.setInt(ins, 1500);

            //Actual output.
            System.out.println("name: " + ins.getName());
            System.out.println("money: " + f.getInt(ins));
            System.out.println(ins.getUserInfo());
        } catch (Exception e) {
            //Output an error.
            System.out.println(e);
        }
    }
}

When you run

Result is...

name: Bob
money: 1500
name: Bob, age: 0, money: 1500

How, the field called money is increasing, You can change the value.

Summary

I introduced only the addition of this field, but since there are various other functions Please use it by all means.

javassist https://github.com/jboss-javassist/javassist

Recommended Posts

I tried metaprogramming in Java
I tried using JWT in Java
I tried using Elasticsearch API in Java
I tried the new era in Java
I tried to implement deep learning in Java
I tried to output multiplication table in Java
I tried to create Alexa skill in Java
I made roulette in Java.
I tried Drools (Java, InputStream)
I tried using Java REPL
I tried Mastodon's Toot and Streaming API in Java
I tried to implement Firebase push notification in Java
I tried using Google Cloud Vision API in Java
# 2 [Note] I tried to calculate multiplication tables in Java.
I tried to create a Clova skill in Java
I tried using an extended for statement in Java
I tried passing Java Silver in 2 weeks without knowing Java
I tried to implement the Euclidean algorithm in Java
I tried to find out what changed in Java 9
I sent an email in Java
I tried to interact with Java
I tried UDP communication with Java
I wrote Goldbach's theorem in java
I tried putting Domino11 in CentOS7
I tried using Java8 Stream API
I made an annotation in Java.
I tried to summarize Java 8 now
I tried using Java memo LocalDate
I tried using GoogleHttpClient of Java
I tried using Dapr in Java to facilitate microservice development
I tried to make a client of RESAS-API in Java
[Java] I participated in ABC-188 of Atcorder.
I tried a calendar problem in Ruby
Partization in Java
I tried Cassandra's Object Mapper for Java
I tried to summarize Java lambda expressions
I tried setting Java beginners to use shortcut keys in eclipse
Rock-paper-scissors in Java
I tried Spring.
I tried tomcat
I tried using OpenCV with Java + Tomcat
I did OpenCV camera calibration in Java
I tried refactoring ①
I tried the AutoValue library in Intellij
Pi in Java
I tried Google's entrance exam (unofficial) [java]
I tried FizzBuzz.
[* Java *] I participated in JJUG CCC 2019 Spring
FizzBuzz in Java
I tried JHipster 5.1
I tried embedding a formula in Javadoc
I tried to make a talk application in Java using AI "A3RT"
I made a primality test program in Java
[For beginners] I tried using DBUnit in Eclipse
I tried putting Java on my Mac easily
I tried to implement polymorphic related in Nogizaka.
[For beginners] I tried using JUnit 5 in Eclipse
I want to send an email in Java.
I tried to organize the session in Rails
java I tried to break a simple block
I tried hitting a Java method from ABCL