您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

CtNewWrappedMethod.java 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. Alternatively, the contents of this file may be used under
  8. * the terms of the GNU Lesser General Public License Version 2.1 or later.
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. */
  15. package javassist;
  16. import javassist.bytecode.*;
  17. import javassist.compiler.JvstCodeGen;
  18. import java.util.Hashtable;
  19. import javassist.CtMethod.ConstParameter;
  20. class CtNewWrappedMethod {
  21. private static final String addedWrappedMethod = "_added_m$";
  22. public static CtMethod wrapped(CtClass returnType, String mname,
  23. CtClass[] parameterTypes,
  24. CtClass[] exceptionTypes,
  25. CtMethod body, ConstParameter constParam,
  26. CtClass declaring)
  27. throws CannotCompileException
  28. {
  29. CtMethod mt = new CtMethod(returnType, mname, parameterTypes,
  30. declaring);
  31. mt.setModifiers(body.getModifiers());
  32. try {
  33. mt.setExceptionTypes(exceptionTypes);
  34. }
  35. catch (NotFoundException e) {
  36. throw new CannotCompileException(e);
  37. }
  38. Bytecode code = makeBody(declaring, declaring.getClassFile2(), body,
  39. parameterTypes, returnType, constParam);
  40. mt.getMethodInfo2().setCodeAttribute(code.toCodeAttribute());
  41. return mt;
  42. }
  43. static Bytecode makeBody(CtClass clazz, ClassFile classfile,
  44. CtMethod wrappedBody,
  45. CtClass[] parameters,
  46. CtClass returnType,
  47. ConstParameter cparam)
  48. throws CannotCompileException
  49. {
  50. boolean isStatic = Modifier.isStatic(wrappedBody.getModifiers());
  51. Bytecode code = new Bytecode(classfile.getConstPool(), 0, 0);
  52. int stacksize = makeBody0(clazz, classfile, wrappedBody, isStatic,
  53. parameters, returnType, cparam, code);
  54. code.setMaxStack(stacksize);
  55. code.setMaxLocals(isStatic, parameters, 0);
  56. return code;
  57. }
  58. /* The generated method body does not need a stack map table
  59. * because it does not contain a branch instruction.
  60. */
  61. protected static int makeBody0(CtClass clazz, ClassFile classfile,
  62. CtMethod wrappedBody,
  63. boolean isStatic, CtClass[] parameters,
  64. CtClass returnType, ConstParameter cparam,
  65. Bytecode code)
  66. throws CannotCompileException
  67. {
  68. if (!(clazz instanceof CtClassType))
  69. throw new CannotCompileException("bad declaring class"
  70. + clazz.getName());
  71. if (!isStatic)
  72. code.addAload(0);
  73. int stacksize = compileParameterList(code, parameters,
  74. (isStatic ? 0 : 1));
  75. int stacksize2;
  76. String desc;
  77. if (cparam == null) {
  78. stacksize2 = 0;
  79. desc = ConstParameter.defaultDescriptor();
  80. }
  81. else {
  82. stacksize2 = cparam.compile(code);
  83. desc = cparam.descriptor();
  84. }
  85. checkSignature(wrappedBody, desc);
  86. String bodyname;
  87. try {
  88. bodyname = addBodyMethod((CtClassType)clazz, classfile,
  89. wrappedBody);
  90. /* if an exception is thrown below, the method added above
  91. * should be removed. (future work :<)
  92. */
  93. }
  94. catch (BadBytecode e) {
  95. throw new CannotCompileException(e);
  96. }
  97. if (isStatic)
  98. code.addInvokestatic(Bytecode.THIS, bodyname, desc);
  99. else
  100. code.addInvokespecial(Bytecode.THIS, bodyname, desc);
  101. compileReturn(code, returnType); // consumes 2 stack entries
  102. if (stacksize < stacksize2 + 2)
  103. stacksize = stacksize2 + 2;
  104. return stacksize;
  105. }
  106. private static void checkSignature(CtMethod wrappedBody,
  107. String descriptor)
  108. throws CannotCompileException
  109. {
  110. if (!descriptor.equals(wrappedBody.getMethodInfo2().getDescriptor()))
  111. throw new CannotCompileException(
  112. "wrapped method with a bad signature: "
  113. + wrappedBody.getDeclaringClass().getName()
  114. + '.' + wrappedBody.getName());
  115. }
  116. private static String addBodyMethod(CtClassType clazz,
  117. ClassFile classfile,
  118. CtMethod src)
  119. throws BadBytecode, CannotCompileException
  120. {
  121. Hashtable bodies = clazz.getHiddenMethods();
  122. String bodyname = (String)bodies.get(src);
  123. if (bodyname == null) {
  124. do {
  125. bodyname = addedWrappedMethod + clazz.getUniqueNumber();
  126. } while (classfile.getMethod(bodyname) != null);
  127. ClassMap map = new ClassMap();
  128. map.put(src.getDeclaringClass().getName(), clazz.getName());
  129. MethodInfo body = new MethodInfo(classfile.getConstPool(),
  130. bodyname, src.getMethodInfo2(),
  131. map);
  132. int acc = body.getAccessFlags();
  133. body.setAccessFlags(AccessFlag.setPrivate(acc));
  134. // a stack map is copied. rebuilding it is not needed.
  135. classfile.addMethod(body);
  136. bodies.put(src, bodyname);
  137. CtMember.Cache cache = clazz.hasMemberCache();
  138. if (cache != null)
  139. cache.addMethod(new CtMethod(body, clazz));
  140. }
  141. return bodyname;
  142. }
  143. /* compileParameterList() returns the stack size used
  144. * by the produced code.
  145. *
  146. * @param regno the index of the local variable in which
  147. * the first argument is received.
  148. * (0: static method, 1: regular method.)
  149. */
  150. static int compileParameterList(Bytecode code,
  151. CtClass[] params, int regno) {
  152. return JvstCodeGen.compileParameterList(code, params, regno);
  153. }
  154. /*
  155. * The produced codes cosume 1 or 2 stack entries.
  156. */
  157. private static void compileReturn(Bytecode code, CtClass type) {
  158. if (type.isPrimitive()) {
  159. CtPrimitiveType pt = (CtPrimitiveType)type;
  160. if (pt != CtClass.voidType) {
  161. String wrapper = pt.getWrapperName();
  162. code.addCheckcast(wrapper);
  163. code.addInvokevirtual(wrapper, pt.getGetMethodName(),
  164. pt.getGetMethodDescriptor());
  165. }
  166. code.addOpcode(pt.getReturnOp());
  167. }
  168. else {
  169. code.addCheckcast(type);
  170. code.addOpcode(Bytecode.ARETURN);
  171. }
  172. }
  173. }