From 8498f89bd3b42a9b61ee32d76bead726be6f2649 Mon Sep 17 00:00:00 2001 From: Tomasz Lelek Date: Thu, 9 Mar 2017 12:15:56 +0100 Subject: [PATCH 1/7] BEEL-634 javassist dependency --- libraries/pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libraries/pom.xml b/libraries/pom.xml index bfcc9b66d538..724c7272cb69 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -47,6 +47,12 @@ jasypt ${jasypt.version} + + javassist + javassist + ${javaassist.version} + + @@ -55,6 +61,7 @@ 3.5 4.12 1.9.2 + 3.3 From 4f04ccbc68dbcd2e2fa81a4667f5821ca73301d1 Mon Sep 17 00:00:00 2001 From: Tomasz Lelek Date: Thu, 9 Mar 2017 14:52:05 +0100 Subject: [PATCH 2/7] BEEL-634 code for javassist article --- .../java/com/baeldung/javasisst/Point.java | 17 +++ .../com/baeldung/javassist/JavasisstTest.java | 118 ++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 libraries/src/main/java/com/baeldung/javasisst/Point.java create mode 100644 libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java diff --git a/libraries/src/main/java/com/baeldung/javasisst/Point.java b/libraries/src/main/java/com/baeldung/javasisst/Point.java new file mode 100644 index 000000000000..857c6c567914 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/javasisst/Point.java @@ -0,0 +1,17 @@ +package com.baeldung.javasisst; + + +public class Point { + private int x; + private int y; + + public Point(int x, int y) { + this.x = x; + this.y = y; + } + + public void move(int x, int y) { + this.x = x; + this.y = y; + } +} diff --git a/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java b/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java new file mode 100644 index 000000000000..83b3fef32e13 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java @@ -0,0 +1,118 @@ +package com.baeldung.javassist; + + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.NotFoundException; +import javassist.bytecode.*; +import org.junit.Test; + +import java.io.DataOutputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class JavasisstTest { + @Test + public void givenJavasisstAPI_whenConstructClass_thenGenerateAClassFile() throws CannotCompileException, IOException { + //given + ClassFile cf = new ClassFile(false, "com.baeldung.JavassistGeneratedClass", null); + cf.setInterfaces(new String[]{"java.lang.Cloneable"}); + + FieldInfo f = new FieldInfo(cf.getConstPool(), "id", "I"); + f.setAccessFlags(AccessFlag.PUBLIC); + cf.addField(f); + + //when + String className = "JavassistGeneratedClass.class"; + cf.write(new DataOutputStream(new FileOutputStream(className))); + + //then + String classContent = new String(Files.readAllBytes(Paths.get(className))); + assertTrue(classContent.contains("java/lang/Cloneable")); + } + + @Test + public void givenJavaClass_whenLoadAtByJavassist_thenTraversWholeClass() throws NotFoundException, CannotCompileException, BadBytecode { + //given + ClassPool cp = ClassPool.getDefault(); + ClassFile cf = cp.get("com.baeldung.javasisst.Point").getClassFile(); + MethodInfo minfo = cf.getMethod("move"); + CodeAttribute ca = minfo.getCodeAttribute(); + CodeIterator ci = ca.iterator(); + + //when + List operations = new LinkedList<>(); + while (ci.hasNext()) { + int index = ci.next(); + int op = ci.byteAt(index); + operations.add(Mnemonic.OPCODE[op]); + } + + //then + assertEquals(operations, + Arrays.asList("aload_0", "iload_1", "putfield", "aload_0", "iload_2", "putfield", "return")); + + } + + @Test + public void givenTableOfInstructions_whenAddNewInstruction_thenShouldConstructProperSequence() throws NotFoundException, BadBytecode { + //given + ClassFile cf = ClassPool.getDefault().get("com.baeldung.javasisst.Point").getClassFile(); + ConstPool cp = cf.getConstPool(); + Bytecode b = new Bytecode(cp, 1, 0); + b.addIconst(3); + b.addReturn(CtClass.intType); + CodeAttribute ca = b.toCodeAttribute(); + CodeIterator ci = ca.iterator(); + + //when + List operations = new LinkedList<>(); + while (ci.hasNext()) { + int index = ci.next(); + int op = ci.byteAt(index); + operations.add(Mnemonic.OPCODE[op]); + } + + //then + assertEquals(operations, + Arrays.asList("iconst_3", "ireturn")); + } + + @Test + public void givenLoadedClass_whenAddConstructorToClass_shouldCreateClassWithConstructor() throws NotFoundException, CannotCompileException, BadBytecode { + //given + ClassFile cf = ClassPool.getDefault().get("com.baeldung.javasisst.Point").getClassFile(); + Bytecode code = new Bytecode(cf.getConstPool()); + code.addAload(0); + code.addInvokespecial("java/lang/Object", MethodInfo.nameInit, "()V"); + code.addReturn(null); + code.setMaxLocals(1); + + //when + MethodInfo minfo = new MethodInfo(cf.getConstPool(), MethodInfo.nameInit, "()V"); + minfo.setCodeAttribute(code.toCodeAttribute()); + cf.addMethod(minfo); + + //then + CodeIterator ci = code.toCodeAttribute().iterator(); + List operations = new LinkedList<>(); + while (ci.hasNext()) { + int index = ci.next(); + int op = ci.byteAt(index); + operations.add(Mnemonic.OPCODE[op]); + } + + operations.contains("invokespecial"); + + + } +} From d59c22326bae2a2a89fd09b89323c9b77341b569 Mon Sep 17 00:00:00 2001 From: Tomasz Lelek Date: Thu, 9 Mar 2017 15:00:08 +0100 Subject: [PATCH 3/7] BEEL-634 test refinement --- .../src/test/java/com/baeldung/javassist/JavasisstTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java b/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java index 83b3fef32e13..2757b935280e 100644 --- a/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java +++ b/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java @@ -95,7 +95,6 @@ public void givenLoadedClass_whenAddConstructorToClass_shouldCreateClassWithCons code.addAload(0); code.addInvokespecial("java/lang/Object", MethodInfo.nameInit, "()V"); code.addReturn(null); - code.setMaxLocals(1); //when MethodInfo minfo = new MethodInfo(cf.getConstPool(), MethodInfo.nameInit, "()V"); @@ -111,7 +110,8 @@ public void givenLoadedClass_whenAddConstructorToClass_shouldCreateClassWithCons operations.add(Mnemonic.OPCODE[op]); } - operations.contains("invokespecial"); + assertEquals(operations, + Arrays.asList("aload_0", "invokespecial", "return")); } From b9e034f3c03c67b6ac8afc0b760637ab2d5124fc Mon Sep 17 00:00:00 2001 From: Tomasz Lelek Date: Fri, 10 Mar 2017 14:38:05 +0100 Subject: [PATCH 4/7] BEEL-634 increment lib to newest version --- libraries/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/pom.xml b/libraries/pom.xml index 724c7272cb69..ea7838ff7094 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -48,7 +48,7 @@ ${jasypt.version} - javassist + org.javassist javassist ${javaassist.version} @@ -61,7 +61,7 @@ 3.5 4.12 1.9.2 - 3.3 + 3.21.0-GA From 3da51bc33f47a15fce6c2e7291c905c0e653391f Mon Sep 17 00:00:00 2001 From: Tomasz Lelek Date: Tue, 14 Mar 2017 16:13:31 +0100 Subject: [PATCH 5/7] add test that uses reflection to verify --- .../com/baeldung/javassist/JavasisstTest.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java b/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java index 2757b935280e..2d868dfd63fb 100644 --- a/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java +++ b/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java @@ -1,16 +1,15 @@ package com.baeldung.javassist; -import javassist.CannotCompileException; -import javassist.ClassPool; -import javassist.CtClass; -import javassist.NotFoundException; +import javassist.*; import javassist.bytecode.*; import org.junit.Test; import java.io.DataOutputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; @@ -22,9 +21,10 @@ public class JavasisstTest { @Test - public void givenJavasisstAPI_whenConstructClass_thenGenerateAClassFile() throws CannotCompileException, IOException { + public void givenJavasisstAPI_whenConstructClass_thenGenerateAClassFile() throws CannotCompileException, IOException, ClassNotFoundException, IllegalAccessException, InstantiationException { //given - ClassFile cf = new ClassFile(false, "com.baeldung.JavassistGeneratedClass", null); + String classNameWithPackage = "com.baeldung.JavassistGeneratedClass"; + ClassFile cf = new ClassFile(false, classNameWithPackage, null); cf.setInterfaces(new String[]{"java.lang.Cloneable"}); FieldInfo f = new FieldInfo(cf.getConstPool(), "id", "I"); @@ -36,6 +36,10 @@ public void givenJavasisstAPI_whenConstructClass_thenGenerateAClassFile() throws cf.write(new DataOutputStream(new FileOutputStream(className))); //then + ClassPool classPool = ClassPool.getDefault(); + Field[] fields = classPool.makeClass(cf).toClass().getFields(); + assertEquals(fields[0].getName(), "id"); + String classContent = new String(Files.readAllBytes(Paths.get(className))); assertTrue(classContent.contains("java/lang/Cloneable")); } @@ -64,7 +68,7 @@ public void givenJavaClass_whenLoadAtByJavassist_thenTraversWholeClass() throws } @Test - public void givenTableOfInstructions_whenAddNewInstruction_thenShouldConstructProperSequence() throws NotFoundException, BadBytecode { + public void givenTableOfInstructions_whenAddNewInstruction_thenShouldConstructProperSequence() throws NotFoundException, BadBytecode, CannotCompileException, IllegalAccessException, InstantiationException { //given ClassFile cf = ClassPool.getDefault().get("com.baeldung.javasisst.Point").getClassFile(); ConstPool cp = cf.getConstPool(); From 9963990271a085e5d1efb30191e6fcec89d5ab88 Mon Sep 17 00:00:00 2001 From: Tomasz Lelek Date: Tue, 14 Mar 2017 16:19:08 +0100 Subject: [PATCH 6/7] add field --- .../java/com/baeldung/javasisst/Point.java | 4 +-- .../com/baeldung/javassist/JavasisstTest.java | 25 ++++++++----------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/libraries/src/main/java/com/baeldung/javasisst/Point.java b/libraries/src/main/java/com/baeldung/javasisst/Point.java index 857c6c567914..7e5c1cedd5cf 100644 --- a/libraries/src/main/java/com/baeldung/javasisst/Point.java +++ b/libraries/src/main/java/com/baeldung/javasisst/Point.java @@ -2,8 +2,8 @@ public class Point { - private int x; - private int y; + public int x = 0; + public int y = 0; public Point(int x, int y) { this.x = x; diff --git a/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java b/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java index 2d868dfd63fb..4c98af85910b 100644 --- a/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java +++ b/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java @@ -71,24 +71,19 @@ public void givenJavaClass_whenLoadAtByJavassist_thenTraversWholeClass() throws public void givenTableOfInstructions_whenAddNewInstruction_thenShouldConstructProperSequence() throws NotFoundException, BadBytecode, CannotCompileException, IllegalAccessException, InstantiationException { //given ClassFile cf = ClassPool.getDefault().get("com.baeldung.javasisst.Point").getClassFile(); - ConstPool cp = cf.getConstPool(); - Bytecode b = new Bytecode(cp, 1, 0); - b.addIconst(3); - b.addReturn(CtClass.intType); - CodeAttribute ca = b.toCodeAttribute(); - CodeIterator ci = ca.iterator(); //when - List operations = new LinkedList<>(); - while (ci.hasNext()) { - int index = ci.next(); - int op = ci.byteAt(index); - operations.add(Mnemonic.OPCODE[op]); - } + FieldInfo f = new FieldInfo(cf.getConstPool(), "id", "I"); + f.setAccessFlags(AccessFlag.PUBLIC); + cf.addField(f); + + + ClassPool classPool = ClassPool.getDefault(); + Field[] fields = classPool.makeClass(cf).toClass().getFields(); + assertEquals(fields[0].getName(), "x"); + assertEquals(fields[1].getName(), "y"); + assertEquals(fields[2].getName(), "id"); - //then - assertEquals(operations, - Arrays.asList("iconst_3", "ireturn")); } @Test From ac263d5c082ba5b2496cefc69d338c84292d725e Mon Sep 17 00:00:00 2001 From: Tomasz Lelek Date: Wed, 15 Mar 2017 09:51:50 +0100 Subject: [PATCH 7/7] add bytecode to different class --- .../javasisst/ThreeDimensionalPoint.java | 19 +++++++++++++++++++ .../com/baeldung/javassist/JavasisstTest.java | 14 ++++++++------ 2 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 libraries/src/main/java/com/baeldung/javasisst/ThreeDimensionalPoint.java diff --git a/libraries/src/main/java/com/baeldung/javasisst/ThreeDimensionalPoint.java b/libraries/src/main/java/com/baeldung/javasisst/ThreeDimensionalPoint.java new file mode 100644 index 000000000000..fb24d4b85d81 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/javasisst/ThreeDimensionalPoint.java @@ -0,0 +1,19 @@ +package com.baeldung.javasisst; + + +public class ThreeDimensionalPoint { + public int x = 0; + public int y = 0; + public int z = 0; + + public ThreeDimensionalPoint(int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + } + + public void move(int x, int y) { + this.x = x; + this.y = y; + } +} diff --git a/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java b/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java index 4c98af85910b..da5ae02c568f 100644 --- a/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java +++ b/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java @@ -1,7 +1,9 @@ package com.baeldung.javassist; -import javassist.*; +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.NotFoundException; import javassist.bytecode.*; import org.junit.Test; @@ -9,12 +11,13 @@ import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.Field; -import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; import java.util.LinkedList; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -70,7 +73,7 @@ public void givenJavaClass_whenLoadAtByJavassist_thenTraversWholeClass() throws @Test public void givenTableOfInstructions_whenAddNewInstruction_thenShouldConstructProperSequence() throws NotFoundException, BadBytecode, CannotCompileException, IllegalAccessException, InstantiationException { //given - ClassFile cf = ClassPool.getDefault().get("com.baeldung.javasisst.Point").getClassFile(); + ClassFile cf = ClassPool.getDefault().get("com.baeldung.javasisst.ThreeDimensionalPoint").getClassFile(); //when FieldInfo f = new FieldInfo(cf.getConstPool(), "id", "I"); @@ -80,9 +83,8 @@ public void givenTableOfInstructions_whenAddNewInstruction_thenShouldConstructPr ClassPool classPool = ClassPool.getDefault(); Field[] fields = classPool.makeClass(cf).toClass().getFields(); - assertEquals(fields[0].getName(), "x"); - assertEquals(fields[1].getName(), "y"); - assertEquals(fields[2].getName(), "id"); + List fieldsList = Stream.of(fields).map(Field::getName).collect(Collectors.toList()); + assertTrue(fieldsList.contains("id")); }