/src/test/java/com/alibaba/json/test/TestASM.java

https://github.com/alibaba/fastjson · Java · 243 lines · 173 code · 42 blank · 28 comment · 45 complexity · f8b17364944c33887153e58060093717 MD5 · raw file

  1. package com.alibaba.json.test;
  2. import java.io.FileOutputStream;
  3. import java.lang.reflect.Method;
  4. import junit.framework.TestCase;
  5. import com.alibaba.fastjson.JSON;
  6. import com.alibaba.fastjson.asm.ClassWriter;
  7. import com.alibaba.fastjson.asm.MethodVisitor;
  8. import com.alibaba.fastjson.asm.MethodWriter;
  9. import com.alibaba.fastjson.asm.Opcodes;
  10. import com.alibaba.fastjson.serializer.JSONSerializer;
  11. import com.alibaba.fastjson.serializer.SerializeWriter;
  12. import com.alibaba.json.test.benchmark.encode.EishayEncode;
  13. public class TestASM extends TestCase implements Opcodes {
  14. // public void test_0() throws Exception {
  15. //
  16. // ClassWriter cw = new ClassWriter(0);
  17. // cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);
  18. //
  19. // MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
  20. // mw.visitVarInsn(ALOAD, 0);
  21. // mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
  22. // mw.visitInsn(RETURN);
  23. // mw.visitMaxs(1, 1);
  24. // mw.visitEnd();
  25. // mw = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
  26. // mw.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
  27. // mw.visitLdcInsn("Hello world!");
  28. // mw.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
  29. // mw.visitInsn(RETURN);
  30. // mw.visitMaxs(2, 2);
  31. // mw.visitEnd();
  32. // byte[] code = cw.toByteArray();
  33. // FileOutputStream fos = new FileOutputStream("Example.class");
  34. // fos.write(code);
  35. // fos.close();
  36. //
  37. // MyClassLoader loader = new MyClassLoader();
  38. //
  39. // Class exampleClass = loader.defineClassF("Example", code, 0, code.length);
  40. // exampleClass.getMethods()[0].invoke(null, new Object[] { null });
  41. // }
  42. public void test_asm() throws Exception {
  43. String text = JSON.toJSONString(EishayEncode.mediaContent);
  44. System.out.println(text);
  45. }
  46. public void test_1() throws Exception {
  47. ClassWriter cw = new ClassWriter();
  48. cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, "DateSerializer", "java/lang/Object", new String[] { "com/alibaba/fastjson/serializer/ObjectSerializer" });
  49. MethodVisitor mw = new MethodWriter(cw, ACC_PUBLIC, "<init>", "()V", null, null);
  50. mw.visitVarInsn(ALOAD, 0);
  51. mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
  52. mw.visitInsn(RETURN);
  53. mw.visitMaxs(1, 1);
  54. mw.visitEnd();
  55. mw = new MethodWriter(cw, ACC_PUBLIC, "write", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;)V", null, new String[] { "java/io/IOException" });
  56. mw.visitVarInsn(ALOAD, 1); // serializer
  57. mw.visitMethodInsn(INVOKEVIRTUAL, "com/alibaba/fastjson/serializer/JSONSerializer", "getWriter", "()Lcom/alibaba/fastjson/serializer/SerializeWriter;");
  58. mw.visitVarInsn(ASTORE, 3); // out
  59. mw.visitVarInsn(ALOAD, 2); // obj
  60. mw.visitTypeInsn(CHECKCAST, getCastType(Entity.class)); // serializer
  61. mw.visitVarInsn(ASTORE, 4); // obj
  62. mw.visitVarInsn(ALOAD, 3); // out
  63. mw.visitLdcInsn("{");
  64. mw.visitMethodInsn(INVOKEVIRTUAL, getCastType(SerializeWriter.class), "writeString", "(Ljava/lang/String;)V");
  65. mw.visitVarInsn(ALOAD, 3); // out
  66. mw.visitLdcInsn("\"id\":");
  67. mw.visitMethodInsn(INVOKEVIRTUAL, getCastType(SerializeWriter.class), "write", "(Ljava/lang/String;)V");
  68. mw.visitVarInsn(ALOAD, 3); // out
  69. mw.visitVarInsn(ALOAD, 4); // entity
  70. mw.visitMethodInsn(INVOKEVIRTUAL, getCastType(Entity.class), "getId", "()I");
  71. mw.visitMethodInsn(INVOKEVIRTUAL, getCastType(SerializeWriter.class), "writeInt", "(I)V");
  72. mw.visitVarInsn(ALOAD, 3); // out
  73. mw.visitLdcInsn("\",name\":");
  74. mw.visitMethodInsn(INVOKEVIRTUAL, getCastType(SerializeWriter.class), "write", "(Ljava/lang/String;)V");
  75. mw.visitVarInsn(ALOAD, 3); // out
  76. mw.visitVarInsn(ALOAD, 4); // entity
  77. mw.visitMethodInsn(INVOKEVIRTUAL, getCastType(Entity.class), "getName", "()Ljava/lang/String;");
  78. mw.visitMethodInsn(INVOKEVIRTUAL, getCastType(SerializeWriter.class), "writeString", "(Ljava/lang/String;)V");
  79. mw.visitInsn(RETURN);
  80. mw.visitMaxs(3, 16);
  81. mw.visitEnd();
  82. byte[] code = cw.toByteArray();
  83. FileOutputStream fos = new FileOutputStream("Example.class");
  84. fos.write(code);
  85. fos.close();
  86. MyClassLoader loader = new MyClassLoader(com.alibaba.fastjson.serializer.ObjectSerializer.class.getClassLoader());
  87. Class<?> exampleClass = loader.defineClassF("DateSerializer", code, 0, code.length);
  88. Method[] methods = exampleClass.getMethods();
  89. Object instance = exampleClass.newInstance();
  90. SerializeWriter out = new SerializeWriter();
  91. JSONSerializer serializer = new JSONSerializer(out);
  92. Entity obj = new Entity();
  93. methods[0].invoke(instance, serializer, obj);
  94. System.out.println(out.toString());
  95. }
  96. String getCastType(Class<?> returnType) {
  97. if (returnType.isPrimitive()) {
  98. return getWrapperType(returnType);
  99. } else {
  100. return getAsmTypeAsString(returnType, false);
  101. }
  102. }
  103. private String getWrapperType(Class<?> type) {
  104. if (Integer.TYPE.equals(type)) {
  105. return Integer.class.getCanonicalName().replaceAll("\\.", "/");
  106. } else if (Boolean.TYPE.equals(type)) {
  107. return Boolean.class.getCanonicalName().replaceAll("\\.", "/");
  108. } else if (Character.TYPE.equals(type)) {
  109. return Character.class.getCanonicalName().replaceAll("\\.", "/");
  110. } else if (Byte.TYPE.equals(type)) {
  111. return Byte.class.getCanonicalName().replaceAll("\\.", "/");
  112. } else if (Short.TYPE.equals(type)) {
  113. return Short.class.getCanonicalName().replaceAll("\\.", "/");
  114. } else if (Float.TYPE.equals(type)) {
  115. return Float.class.getCanonicalName().replaceAll("\\.", "/");
  116. } else if (Long.TYPE.equals(type)) {
  117. return Long.class.getCanonicalName().replaceAll("\\.", "/");
  118. } else if (Double.TYPE.equals(type)) {
  119. return Double.class.getCanonicalName().replaceAll("\\.", "/");
  120. } else if (Void.TYPE.equals(type)) {
  121. return Void.class.getCanonicalName().replaceAll("\\.", "/");
  122. }
  123. throw new IllegalStateException("Type: " + type.getCanonicalName() + " is not a primitive type");
  124. }
  125. public String getAsmTypeAsString(Class<?> parameterType, boolean wrap) {
  126. if (parameterType.isArray()) {
  127. if (parameterType.getComponentType().isPrimitive()) {
  128. Class<?> componentType = parameterType.getComponentType();
  129. return "[" + getPrimitiveLetter(componentType);
  130. } else {
  131. return "[" + getAsmTypeAsString(parameterType.getComponentType(), true);
  132. }
  133. } else {
  134. if (!parameterType.isPrimitive()) {
  135. String clsName = parameterType.getCanonicalName();
  136. if (parameterType.isMemberClass()) {
  137. int lastDot = clsName.lastIndexOf(".");
  138. clsName = clsName.substring(0, lastDot) + "$" + clsName.substring(lastDot + 1);
  139. }
  140. if (wrap) {
  141. return "L" + clsName.replaceAll("\\.", "/") + ";";
  142. } else {
  143. return clsName.replaceAll("\\.", "/");
  144. }
  145. } else {
  146. return getPrimitiveLetter(parameterType);
  147. }
  148. }
  149. }
  150. private String getPrimitiveLetter(Class<?> type) {
  151. if (Integer.TYPE.equals(type)) {
  152. return "I";
  153. } else if (Void.TYPE.equals(type)) {
  154. return "V";
  155. } else if (Boolean.TYPE.equals(type)) {
  156. return "Z";
  157. } else if (Character.TYPE.equals(type)) {
  158. return "C";
  159. } else if (Byte.TYPE.equals(type)) {
  160. return "B";
  161. } else if (Short.TYPE.equals(type)) {
  162. return "S";
  163. } else if (Float.TYPE.equals(type)) {
  164. return "F";
  165. } else if (Long.TYPE.equals(type)) {
  166. return "J";
  167. } else if (Double.TYPE.equals(type)) {
  168. return "D";
  169. }
  170. throw new IllegalStateException("Type: " + type.getCanonicalName() + " is not a primitive type");
  171. }
  172. public static class Entity {
  173. private int id;
  174. private String name;
  175. public int getId() {
  176. return id;
  177. }
  178. public void setId(int id) {
  179. this.id = id;
  180. }
  181. public String getName() {
  182. return name;
  183. }
  184. public void setName(String name) {
  185. this.name = name;
  186. }
  187. }
  188. public static class MyClassLoader extends ClassLoader {
  189. public MyClassLoader(ClassLoader parent){
  190. super(parent);
  191. }
  192. public Class<?> defineClassF(String name, byte[] b, int off, int len) throws ClassFormatError {
  193. return defineClass(name, b, off, len, null);
  194. }
  195. }
  196. public static class Foo {
  197. public void execute() {
  198. System.out.println("Hello World");
  199. }
  200. }
  201. }