You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

LazyClassGen.java 66KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926
  1. /* *******************************************************************
  2. * Copyright (c) 2002-2010 Contributors
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v 2.0
  6. * which accompanies this distribution and is available at
  7. * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * Andy Clement 6Jul05 generics - signature attribute
  12. * Abraham Nevado
  13. * ******************************************************************/
  14. package org.aspectj.weaver.bcel;
  15. import java.io.ByteArrayOutputStream;
  16. import java.io.File;
  17. import java.io.IOException;
  18. import java.io.PrintStream;
  19. import java.lang.reflect.Modifier;
  20. import java.util.ArrayList;
  21. import java.util.Collection;
  22. import java.util.Collections;
  23. import java.util.Comparator;
  24. import java.util.HashMap;
  25. import java.util.Iterator;
  26. import java.util.List;
  27. import java.util.Map;
  28. import java.util.Set;
  29. import java.util.SortedMap;
  30. import java.util.TreeMap;
  31. import java.util.Vector;
  32. import org.aspectj.apache.bcel.Constants;
  33. import org.aspectj.apache.bcel.classfile.Attribute;
  34. import org.aspectj.apache.bcel.classfile.ConstantPool;
  35. import org.aspectj.apache.bcel.classfile.Field;
  36. import org.aspectj.apache.bcel.classfile.JavaClass;
  37. import org.aspectj.apache.bcel.classfile.Method;
  38. import org.aspectj.apache.bcel.classfile.Signature;
  39. import org.aspectj.apache.bcel.classfile.Synthetic;
  40. import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
  41. import org.aspectj.apache.bcel.generic.BasicType;
  42. import org.aspectj.apache.bcel.generic.ClassGen;
  43. import org.aspectj.apache.bcel.generic.FieldGen;
  44. import org.aspectj.apache.bcel.generic.InstructionConstants;
  45. import org.aspectj.apache.bcel.generic.InstructionFactory;
  46. import org.aspectj.apache.bcel.generic.InstructionHandle;
  47. import org.aspectj.apache.bcel.generic.InstructionList;
  48. import org.aspectj.apache.bcel.generic.ObjectType;
  49. import org.aspectj.apache.bcel.generic.Type;
  50. import org.aspectj.bridge.IMessage;
  51. import org.aspectj.bridge.ISourceLocation;
  52. import org.aspectj.bridge.SourceLocation;
  53. import org.aspectj.weaver.AjAttribute;
  54. import org.aspectj.weaver.AjAttribute.WeaverState;
  55. import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
  56. import org.aspectj.weaver.BCException;
  57. import org.aspectj.weaver.Member;
  58. import org.aspectj.weaver.MemberKind;
  59. import org.aspectj.weaver.NameMangler;
  60. import org.aspectj.weaver.ResolvedMember;
  61. import org.aspectj.weaver.ResolvedType;
  62. import org.aspectj.weaver.RuntimeVersion;
  63. import org.aspectj.weaver.Shadow;
  64. import org.aspectj.weaver.SignatureUtils;
  65. import org.aspectj.weaver.TypeVariable;
  66. import org.aspectj.weaver.UnresolvedType;
  67. import org.aspectj.weaver.UnresolvedType.TypeKind;
  68. import org.aspectj.weaver.WeaverMessages;
  69. import org.aspectj.weaver.WeaverStateInfo;
  70. import org.aspectj.weaver.World;
  71. import org.aspectj.weaver.bcel.asm.AsmDetector;
  72. import org.aspectj.weaver.bcel.asm.StackMapAdder;
  73. /**
  74. * Lazy lazy lazy. We don't unpack the underlying class unless necessary. Things like new methods and annotations accumulate in here
  75. * until they must be written out, don't add them to the underlying MethodGen! Things are slightly different if this represents an
  76. * Aspect.
  77. */
  78. public final class LazyClassGen {
  79. private static final Type[] ARRAY_7STRING_INT = new Type[] { Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING,
  80. Type.STRING, Type.STRING, Type.INT };
  81. private static final Type[] ARRAY_8STRING_INT = new Type[] { Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING,
  82. Type.STRING, Type.STRING, Type.STRING, Type.INT };
  83. private static final Type[] PARAMSIGNATURE_MAKESJP_METHOD = new Type[] {
  84. Type.STRING, Type.INT, Type.STRING, Type.CLASS, Type.CLASS_ARRAY, Type.STRING_ARRAY, Type.CLASS_ARRAY, Type.CLASS, Type.INT
  85. };
  86. private static final Type[] PARAMSIGNATURE_MAKESJP_CONSTRUCTOR = new Type[] {
  87. Type.STRING, Type.INT, Type.CLASS, Type.CLASS_ARRAY, Type.STRING_ARRAY, Type.CLASS_ARRAY, Type.INT
  88. };
  89. private static final Type[] PARAMSIGNATURE_MAKESJP_CATCHCLAUSE = new Type[] {
  90. Type.STRING, Type.CLASS, Type.CLASS, Type.STRING, Type.INT
  91. };
  92. private static final Type[] PARAMSIGNATURE_MAKESJP_FIELD = new Type[] {
  93. Type.STRING, Type.INT, Type.STRING, Type.CLASS, Type.CLASS, Type.INT
  94. };
  95. private static final Type[] PARAMSIGNATURE_MAKESJP_INITIALIZER = new Type[] {
  96. Type.STRING, Type.INT, Type.CLASS, Type.INT
  97. };
  98. private static final Type[] PARAMSIGNATURE_MAKESJP_MONITOR = new Type[] {
  99. Type.STRING, Type.CLASS, Type.INT
  100. };
  101. private static final Type[] PARAMSIGNATURE_MAKESJP_ADVICE = new Type[] {
  102. Type.STRING, Type.INT, Type.STRING, Type.CLASS, Type.CLASS_ARRAY, Type.STRING_ARRAY,
  103. Type.CLASS_ARRAY, Type.CLASS, Type.INT
  104. };
  105. private static final int ACC_SYNTHETIC = 0x1000;
  106. private static final String[] NO_STRINGS = new String[0];
  107. int highestLineNumber = 0; // ---- JSR 45 info
  108. private final SortedMap<String, InlinedSourceFileInfo> inlinedFiles = new TreeMap<>();
  109. private boolean regenerateGenericSignatureAttribute = false;
  110. private BcelObjectType myType; // XXX is not set for types we create
  111. private ClassGen myGen;
  112. private final ConstantPool cp;
  113. private final World world;
  114. private final String packageName = null;
  115. private final List<BcelField> fields = new ArrayList<>();
  116. private final List<LazyMethodGen> methodGens = new ArrayList<>();
  117. private final List<LazyClassGen> classGens = new ArrayList<>();
  118. private final List<AnnotationGen> annotations = new ArrayList<>();
  119. private int childCounter = 0;
  120. private final InstructionFactory fact;
  121. private boolean isSerializable = false;
  122. private boolean hasSerialVersionUIDField = false;
  123. private boolean serialVersionUIDRequiresInitialization = false;
  124. private long calculatedSerialVersionUID;
  125. private boolean hasClinit = false;
  126. private ResolvedType[] extraSuperInterfaces = null;
  127. private ResolvedType superclass = null;
  128. // ---
  129. static class InlinedSourceFileInfo {
  130. int highestLineNumber;
  131. int offset; // calculated
  132. InlinedSourceFileInfo(int highestLineNumber) {
  133. this.highestLineNumber = highestLineNumber;
  134. }
  135. }
  136. void addInlinedSourceFileInfo(String fullpath, int highestLineNumber) {
  137. Object o = inlinedFiles.get(fullpath);
  138. if (o != null) {
  139. InlinedSourceFileInfo info = (InlinedSourceFileInfo) o;
  140. if (info.highestLineNumber < highestLineNumber) {
  141. info.highestLineNumber = highestLineNumber;
  142. }
  143. } else {
  144. inlinedFiles.put(fullpath, new InlinedSourceFileInfo(highestLineNumber));
  145. }
  146. }
  147. void calculateSourceDebugExtensionOffsets() {
  148. int i = roundUpToHundreds(highestLineNumber);
  149. for (InlinedSourceFileInfo element : inlinedFiles.values()) {
  150. element.offset = i;
  151. i = roundUpToHundreds(i + element.highestLineNumber);
  152. }
  153. }
  154. private static int roundUpToHundreds(int i) {
  155. return ((i / 100) + 1) * 100;
  156. }
  157. int getSourceDebugExtensionOffset(String fullpath) {
  158. return inlinedFiles.get(fullpath).offset;
  159. }
  160. // private Unknown getSourceDebugExtensionAttribute() {
  161. // int nameIndex = cp.addUtf8("SourceDebugExtension");
  162. // String data = getSourceDebugExtensionString();
  163. // //System.err.println(data);
  164. // byte[] bytes = Utility.stringToUTF(data);
  165. // int length = bytes.length;
  166. //
  167. // return new Unknown(nameIndex, length, bytes, cp);
  168. // }
  169. // private LazyClassGen() {}
  170. // public static void main(String[] args) {
  171. // LazyClassGen m = new LazyClassGen();
  172. // m.highestLineNumber = 37;
  173. // m.inlinedFiles.put("boo/baz/foo.java", new InlinedSourceFileInfo( 83));
  174. // m.inlinedFiles.put("boo/barz/foo.java", new InlinedSourceFileInfo(292));
  175. // m.inlinedFiles.put("boo/baz/moo.java", new InlinedSourceFileInfo(128));
  176. // m.calculateSourceDebugExtensionOffsets();
  177. // System.err.println(m.getSourceDebugExtensionString());
  178. // }
  179. // For the entire pathname, we're using package names. This is probably
  180. // wrong.
  181. // private String getSourceDebugExtensionString() {
  182. // StringBuffer out = new StringBuffer();
  183. // String myFileName = getFileName();
  184. // // header section
  185. // out.append("SMAP\n");
  186. // out.append(myFileName);
  187. // out.append("\nAspectJ\n");
  188. // // stratum section
  189. // out.append("*S AspectJ\n");
  190. // // file section
  191. // out.append("*F\n");
  192. // out.append("1 ");
  193. // out.append(myFileName);
  194. // out.append("\n");
  195. // int i = 2;
  196. // for (Iterator iter = inlinedFiles.keySet().iterator(); iter.hasNext();) {
  197. // String element = (String) iter.next();
  198. // int ii = element.lastIndexOf('/');
  199. // if (ii == -1) {
  200. // out.append(i++); out.append(' ');
  201. // out.append(element); out.append('\n');
  202. // } else {
  203. // out.append("+ "); out.append(i++); out.append(' ');
  204. // out.append(element.substring(ii+1)); out.append('\n');
  205. // out.append(element); out.append('\n');
  206. // }
  207. // }
  208. // // emit line section
  209. // out.append("*L\n");
  210. // out.append("1#1,");
  211. // out.append(highestLineNumber);
  212. // out.append(":1,1\n");
  213. // i = 2;
  214. // for (Iterator iter = inlinedFiles.values().iterator(); iter.hasNext();) {
  215. // InlinedSourceFileInfo element = (InlinedSourceFileInfo) iter.next();
  216. // out.append("1#");
  217. // out.append(i++); out.append(',');
  218. // out.append(element.highestLineNumber); out.append(":");
  219. // out.append(element.offset + 1); out.append(",1\n");
  220. // }
  221. // // end section
  222. // out.append("*E\n");
  223. // // and finish up...
  224. // return out.toString();
  225. // }
  226. // ---- end JSR45-related stuff
  227. /** Emit disassembled class and newline to out */
  228. public static void disassemble(String path, String name, PrintStream out) throws IOException {
  229. if (null == out) {
  230. return;
  231. }
  232. // out.println("classPath: " + classPath);
  233. BcelWorld world = new BcelWorld(path);
  234. UnresolvedType ut = UnresolvedType.forName(name);
  235. ut.setNeedsModifiableDelegate(true);
  236. LazyClassGen clazz = new LazyClassGen(BcelWorld.getBcelObjectType(world.resolve(ut)));
  237. clazz.print(out);
  238. out.println();
  239. }
  240. public String getNewGeneratedNameTag() {
  241. return Integer.toString(childCounter++);
  242. }
  243. // ----
  244. public LazyClassGen(String class_name, String super_class_name, String file_name, int access_flags, String[] interfaces,
  245. World world) {
  246. myGen = new ClassGen(class_name, super_class_name, file_name, access_flags, interfaces);
  247. cp = myGen.getConstantPool();
  248. fact = new InstructionFactory(myGen, cp);
  249. regenerateGenericSignatureAttribute = true;
  250. this.world = world;
  251. }
  252. public void setMajorMinor(int major, int minor) {
  253. myGen.setMajor(major);
  254. myGen.setMinor(minor);
  255. }
  256. public int getMajor() {
  257. return myGen.getMajor();
  258. }
  259. public int getMinor() {
  260. return myGen.getMinor();
  261. }
  262. // Non child type, so it comes from a real type in the world.
  263. public LazyClassGen(BcelObjectType myType) {
  264. myGen = new ClassGen(myType.getJavaClass());
  265. cp = myGen.getConstantPool();
  266. fact = new InstructionFactory(myGen, cp);
  267. this.myType = myType;
  268. world = myType.getResolvedTypeX().getWorld();
  269. /* Does this class support serialization */
  270. if (implementsSerializable(getType())) {
  271. isSerializable = true;
  272. // ResolvedMember[] fields = getType().getDeclaredFields();
  273. // for (int i = 0; i < fields.length; i++) {
  274. // ResolvedMember field = fields[i];
  275. // if (field.getName().equals("serialVersionUID")
  276. // && field.isStatic() && field.getType().equals(UnresolvedType.LONG))
  277. // {
  278. // hasSerialVersionUIDField = true;
  279. // }
  280. // }
  281. hasSerialVersionUIDField = hasSerialVersionUIDField(getType());
  282. ResolvedMember[] methods = getType().getDeclaredMethods();
  283. for (ResolvedMember method : methods) {
  284. if (method.getName().equals("<clinit>")) {
  285. if (method.getKind() != Member.STATIC_INITIALIZATION) {
  286. throw new RuntimeException("qui?");
  287. }
  288. hasClinit = true;
  289. }
  290. }
  291. // Do we need to calculate an SUID and add it?
  292. if (!getType().isInterface() && !hasSerialVersionUIDField && world.isAddSerialVerUID()) {
  293. calculatedSerialVersionUID = myGen.getSUID();
  294. FieldGen fg = new FieldGen(Constants.ACC_PRIVATE | Constants.ACC_FINAL | Constants.ACC_STATIC, BasicType.LONG,
  295. "serialVersionUID", getConstantPool());
  296. addField(fg);
  297. hasSerialVersionUIDField = true;
  298. serialVersionUIDRequiresInitialization = true;
  299. // warn about what we've done?
  300. if (world.getLint().calculatingSerialVersionUID.isEnabled()) {
  301. world.getLint().calculatingSerialVersionUID.signal(
  302. new String[] { getClassName(), Long.toString(calculatedSerialVersionUID) + "L" }, null, null);
  303. }
  304. }
  305. }
  306. ResolvedMember[] methods = myType.getDeclaredMethods();
  307. for (ResolvedMember method : methods) {
  308. addMethodGen(new LazyMethodGen((BcelMethod) method, this));
  309. }
  310. // Method[] methods = myGen.getMethods();
  311. // for (int i = 0; i < methods.length; i++) {
  312. // addMethodGen(new LazyMethodGen(methods[i], this));
  313. // }
  314. ResolvedMember[] fields = myType.getDeclaredFields();
  315. for (ResolvedMember field : fields) {
  316. this.fields.add((BcelField) field);
  317. }
  318. }
  319. public static boolean hasSerialVersionUIDField(ResolvedType type) {
  320. ResolvedMember[] fields = type.getDeclaredFields();
  321. for (ResolvedMember field : fields) {
  322. if (field.getName().equals("serialVersionUID") && Modifier.isStatic(field.getModifiers())
  323. && field.getType().equals(UnresolvedType.LONG)) {
  324. return true;
  325. }
  326. }
  327. return false;
  328. }
  329. // public void addAttribute(Attribute i) {
  330. // myGen.addAttribute(i);
  331. // }
  332. // ----
  333. public String getInternalClassName() {
  334. return getConstantPool().getConstantString_CONSTANTClass(myGen.getClassNameIndex());
  335. // getConstantPool().getConstantString(
  336. // myGen.getClassNameIndex(),
  337. // Constants.CONSTANT_Class);
  338. }
  339. public String getInternalFileName() {
  340. String str = getInternalClassName();
  341. int index = str.lastIndexOf('/');
  342. if (index == -1) {
  343. return getFileName();
  344. } else {
  345. return str.substring(0, index + 1) + getFileName();
  346. }
  347. }
  348. /**
  349. * Returns the packagename - if its the default package we return an empty string
  350. */
  351. public String getPackageName() {
  352. if (packageName != null) {
  353. return packageName;
  354. }
  355. String str = getInternalClassName();
  356. int index = str.indexOf("<");
  357. if (index != -1) {
  358. str = str.substring(0, index); // strip off the generics guff
  359. }
  360. index = str.lastIndexOf("/");
  361. if (index == -1) {
  362. return "";
  363. }
  364. return str.substring(0, index).replace('/', '.');
  365. }
  366. public void addMethodGen(LazyMethodGen gen) {
  367. // assert gen.getClassName() == super.getClassName();
  368. methodGens.add(gen);
  369. if (highestLineNumber < gen.highestLineNumber) {
  370. highestLineNumber = gen.highestLineNumber;
  371. }
  372. }
  373. public boolean removeMethodGen(LazyMethodGen gen) {
  374. return methodGens.remove(gen);
  375. }
  376. public void addMethodGen(LazyMethodGen gen, ISourceLocation sourceLocation) {
  377. addMethodGen(gen);
  378. if (!gen.getMethod().isPrivate()) {
  379. warnOnAddedMethod(gen.getMethod(), sourceLocation);
  380. }
  381. }
  382. public void errorOnAddedField(FieldGen field, ISourceLocation sourceLocation) {
  383. if (isSerializable && !hasSerialVersionUIDField) {
  384. getWorld().getLint().serialVersionUIDBroken.signal(
  385. new String[] { myType.getResolvedTypeX().getName(), field.getName() }, sourceLocation, null);
  386. }
  387. }
  388. public void warnOnAddedInterface(String name, ISourceLocation sourceLocation) {
  389. warnOnModifiedSerialVersionUID(sourceLocation, "added interface " + name);
  390. }
  391. public void warnOnAddedMethod(Method method, ISourceLocation sourceLocation) {
  392. warnOnModifiedSerialVersionUID(sourceLocation, "added non-private method " + method.getName());
  393. }
  394. public void warnOnAddedStaticInitializer(Shadow shadow, ISourceLocation sourceLocation) {
  395. if (!hasClinit) {
  396. warnOnModifiedSerialVersionUID(sourceLocation, "added static initializer");
  397. }
  398. }
  399. public void warnOnModifiedSerialVersionUID(ISourceLocation sourceLocation, String reason) {
  400. if (isSerializable && !hasSerialVersionUIDField) {
  401. getWorld().getLint().needsSerialVersionUIDField.signal(new String[] { myType.getResolvedTypeX().getName().toString(),
  402. reason }, sourceLocation, null);
  403. }
  404. }
  405. public World getWorld() {
  406. return world;
  407. }
  408. public List<LazyMethodGen> getMethodGens() {
  409. return methodGens; // ???Collections.unmodifiableList(methodGens);
  410. }
  411. public List<BcelField> getFieldGens() {
  412. return fields;
  413. }
  414. public boolean fieldExists(String name) {
  415. // Field[] allFields = myGen.getFields();
  416. // if (allFields!=null) {
  417. // for (int i=0;i<allFields.length;i++) {
  418. // Field f = allFields[i];
  419. // if (f.getName().equals(name)) {
  420. // return f;
  421. // }
  422. // }
  423. // }
  424. for (BcelField f: fields) {
  425. if (f.getName().equals(name)) {
  426. return true;
  427. }
  428. }
  429. return false;
  430. }
  431. private void writeBack(BcelWorld world) {
  432. if (getConstantPool().getSize() > Short.MAX_VALUE) {
  433. reportClassTooBigProblem();
  434. return;
  435. }
  436. if (annotations.size() > 0) {
  437. for (AnnotationGen element : annotations) {
  438. myGen.addAnnotation(element);
  439. }
  440. // Attribute[] annAttributes =
  441. // org.aspectj.apache.bcel.classfile.Utility.getAnnotationAttributes(
  442. // getConstantPool(),annotations);
  443. // for (int i = 0; i < annAttributes.length; i++) {
  444. // Attribute attribute = annAttributes[i];
  445. // System.err.println("Adding attribute for "+attribute);
  446. // myGen.addAttribute(attribute);
  447. // }
  448. }
  449. // Add a weaver version attribute to the file being produced (if
  450. // necessary...)
  451. if (!myGen.hasAttribute("org.aspectj.weaver.WeaverVersion")) {
  452. myGen.addAttribute(Utility.bcelAttribute(new AjAttribute.WeaverVersionInfo(), getConstantPool()));
  453. }
  454. // see 389678: TODO more finessing possible here?
  455. if (world.isOverWeaving()) {
  456. if (myGen.hasAttribute(WeaverState.AttributeName) && myType!=null && myType.getWeaverState() != null) {
  457. myGen.removeAttribute(myGen.getAttribute(WeaverState.AttributeName));
  458. myGen.addAttribute(Utility.bcelAttribute(new AjAttribute.WeaverState(myType.getWeaverState()), getConstantPool()));
  459. }
  460. } else {
  461. if (!myGen.hasAttribute(WeaverState.AttributeName) && myType != null && myType.getWeaverState() != null) {
  462. myGen.addAttribute(Utility.bcelAttribute(new AjAttribute.WeaverState(myType.getWeaverState()), getConstantPool()));
  463. }
  464. }
  465. // FIXME ATAJ needed only for slow Aspects.aspectOf() - keep or remove
  466. // make a lot of test fail since the test compare weaved class file
  467. // based on some test data as text files...
  468. // if (!myGen.isInterface()) {
  469. // addAjClassField();
  470. // }
  471. addAjcInitializers();
  472. // 17Feb05 - ASC - Skip this for now - it crashes IBM 1.4.2 jvms
  473. // (pr80430). Will be revisited when contents
  474. // of attribute are confirmed to be correct.
  475. boolean sourceDebugExtensionSupportSwitchedOn = false;
  476. if (sourceDebugExtensionSupportSwitchedOn) {
  477. calculateSourceDebugExtensionOffsets();
  478. }
  479. int len = methodGens.size();
  480. myGen.setMethods(Method.NoMethods);
  481. for (LazyMethodGen gen : methodGens) {
  482. // we skip empty clinits
  483. if (isEmptyClinit(gen)) {
  484. continue;
  485. }
  486. myGen.addMethod(gen.getMethod());
  487. }
  488. len = fields.size();
  489. myGen.setFields(Field.NoFields);
  490. for (int i = 0; i < len; i++) {
  491. BcelField gen = fields.get(i);
  492. myGen.addField(gen.getField(cp));
  493. }
  494. if (sourceDebugExtensionSupportSwitchedOn) {
  495. if (inlinedFiles.size() != 0) {
  496. if (hasSourceDebugExtensionAttribute(myGen)) {
  497. world.showMessage(IMessage.WARNING, WeaverMessages.format(WeaverMessages.OVERWRITE_JSR45, getFileName()), null,
  498. null);
  499. }
  500. // myGen.addAttribute(getSourceDebugExtensionAttribute());
  501. }
  502. }
  503. fixupGenericSignatureAttribute();
  504. }
  505. /**
  506. * When working with Java generics, a signature attribute is attached to the type which indicates how it was declared. This
  507. * routine ensures the signature attribute for the class we are about to write out is correct. Basically its responsibilities
  508. * are:
  509. * <ol>
  510. * <li>
  511. * Checking whether the attribute needs changing (ie. did weaving change the type hierarchy) - if it did, remove the old
  512. * attribute
  513. * <li>
  514. * Check if we need an attribute at all, are we generic? are our supertypes parameterized/generic?
  515. * <li>
  516. * Build the new attribute which includes all typevariable, supertype and superinterface information
  517. * </ol>
  518. */
  519. private void fixupGenericSignatureAttribute() {
  520. if (getWorld() != null && !getWorld().isInJava5Mode()) {
  521. return;
  522. }
  523. // TODO asc generics Temporarily assume that types we generate dont need
  524. // a signature attribute (closure/etc).. will need
  525. // revisiting no doubt...
  526. // if (myType == null) {
  527. // return;
  528. // }
  529. // 1. Has anything changed that would require us to modify this
  530. // attribute?
  531. if (!regenerateGenericSignatureAttribute) {
  532. return;
  533. }
  534. // 2. Find the old attribute
  535. Signature sigAttr = null;
  536. if (myType != null) { // if null, this is a type built from scratch, it
  537. // won't already have a sig attribute
  538. sigAttr = (Signature) myGen.getAttribute("Signature");
  539. }
  540. // 3. Do we need an attribute?
  541. boolean needAttribute = false;
  542. // If we had one before, we definetly still need one as types can't be
  543. // 'removed' from the hierarchy
  544. if (sigAttr != null) {
  545. needAttribute = true;
  546. }
  547. // check the interfaces
  548. if (!needAttribute) {
  549. if (myType != null) {
  550. ResolvedType[] interfaceRTXs = myType.getDeclaredInterfaces();
  551. for (ResolvedType typeX : interfaceRTXs) {
  552. if (typeX.isGenericType() || typeX.isParameterizedType()) {
  553. needAttribute = true;
  554. }
  555. }
  556. if (extraSuperInterfaces != null) {
  557. for (ResolvedType interfaceType : extraSuperInterfaces) {
  558. if (interfaceType.isGenericType() || interfaceType.isParameterizedType()) {
  559. needAttribute = true;
  560. }
  561. }
  562. }
  563. }
  564. if (myType == null) {
  565. ResolvedType superclassRTX = superclass;
  566. if (superclassRTX != null) {
  567. if (superclassRTX.isGenericType() || superclassRTX.isParameterizedType()) {
  568. needAttribute = true;
  569. }
  570. }
  571. } else {
  572. // check the supertype
  573. ResolvedType superclassRTX = getSuperClass();
  574. if (superclassRTX.isGenericType() || superclassRTX.isParameterizedType()) {
  575. needAttribute = true;
  576. }
  577. }
  578. }
  579. if (needAttribute) {
  580. StringBuilder signature = new StringBuilder();
  581. // first, the type variables...
  582. if (myType != null) {
  583. TypeVariable[] tVars = myType.getTypeVariables();
  584. if (tVars.length > 0) {
  585. signature.append("<");
  586. for (TypeVariable variable : tVars) {
  587. signature.append(variable.getSignatureForAttribute());
  588. }
  589. signature.append(">");
  590. }
  591. }
  592. // now the supertype
  593. String supersig = getSuperClass().getSignatureForAttribute();
  594. signature.append(supersig);
  595. if (myType != null) {
  596. ResolvedType[] interfaceRTXs = myType.getDeclaredInterfaces();
  597. for (ResolvedType interfaceRTX : interfaceRTXs) {
  598. String s = interfaceRTX.getSignatureForAttribute();
  599. signature.append(s);
  600. }
  601. if (extraSuperInterfaces != null) {
  602. for (ResolvedType extraSuperInterface : extraSuperInterfaces) {
  603. String s = extraSuperInterface.getSignatureForAttribute();
  604. signature.append(s);
  605. }
  606. }
  607. }
  608. if (sigAttr != null) {
  609. myGen.removeAttribute(sigAttr);
  610. }
  611. myGen.addAttribute(createSignatureAttribute(signature.toString()));
  612. }
  613. }
  614. /**
  615. * Helper method to create a signature attribute based on a string signature: e.g. "Ljava/lang/Object;LI<Ljava/lang/Double;>;"
  616. */
  617. private Signature createSignatureAttribute(String signature) {
  618. int nameIndex = cp.addUtf8("Signature");
  619. int sigIndex = cp.addUtf8(signature);
  620. return new Signature(nameIndex, 2, sigIndex, cp);
  621. }
  622. /**
  623. *
  624. */
  625. private void reportClassTooBigProblem() {
  626. // PR 59208
  627. // we've generated a class that is just toooooooooo big (you've been
  628. // generating programs
  629. // again haven't you? come on, admit it, no-one writes classes this big
  630. // by hand).
  631. // create an empty myGen so that we can give back a return value that
  632. // doesn't upset the
  633. // rest of the process.
  634. myGen = new ClassGen(myGen.getClassName(), myGen.getSuperclassName(), myGen.getFileName(), myGen.getModifiers(),
  635. myGen.getInterfaceNames());
  636. // raise an error against this compilation unit.
  637. getWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.CLASS_TOO_BIG, this.getClassName()),
  638. new SourceLocation(new File(myGen.getFileName()), 0), null);
  639. }
  640. private static boolean hasSourceDebugExtensionAttribute(ClassGen gen) {
  641. return gen.hasAttribute("SourceDebugExtension");
  642. }
  643. public JavaClass getJavaClass(BcelWorld world) {
  644. writeBack(world);
  645. return myGen.getJavaClass();
  646. }
  647. public byte[] getJavaClassBytesIncludingReweavable(BcelWorld world) {
  648. writeBack(world);
  649. byte[] wovenClassFileData = myGen.getJavaClass().getBytes();
  650. // At 1.6 stackmaps are optional, whilst at 1.7 and later they
  651. // are required (unless turning off the verifier)
  652. if ((myGen.getMajor() == Constants.MAJOR_1_6 && world.shouldGenerateStackMaps()) || myGen.getMajor() > Constants.MAJOR_1_6) {
  653. if (!AsmDetector.isAsmAround) {
  654. throw new BCException(
  655. "Unable to find ASM classes (" + AsmDetector.CLASS_READER + ", " + AsmDetector.CLASS_VISITOR + ") " +
  656. "for stackmap generation. Stackmap generation for woven code is required to avoid verify errors " +
  657. "on a Java 1.7 or higher runtime."
  658. );
  659. }
  660. wovenClassFileData = StackMapAdder.addStackMaps(world, wovenClassFileData);
  661. }
  662. WeaverStateInfo wsi = myType.getWeaverState();// getOrCreateWeaverStateInfo();
  663. if (wsi != null && wsi.isReweavable() && !world.isOverWeaving()) { // && !reweavableDataInserted
  664. // reweavableDataInserted = true;
  665. return wsi.replaceKeyWithDiff(wovenClassFileData);
  666. } else {
  667. return wovenClassFileData;
  668. }
  669. }
  670. public void addGeneratedInner(LazyClassGen newClass) {
  671. classGens.add(newClass);
  672. }
  673. public void addInterface(ResolvedType newInterface, ISourceLocation sourceLocation) {
  674. regenerateGenericSignatureAttribute = true;
  675. if (extraSuperInterfaces == null) {
  676. extraSuperInterfaces = new ResolvedType[1];
  677. extraSuperInterfaces[0] = newInterface;
  678. } else {
  679. ResolvedType[] x = new ResolvedType[extraSuperInterfaces.length + 1];
  680. System.arraycopy(extraSuperInterfaces, 0, x, 1, extraSuperInterfaces.length);
  681. x[0] = newInterface;
  682. extraSuperInterfaces = x;
  683. }
  684. myGen.addInterface(newInterface.getRawName());
  685. if (!newInterface.equals(UnresolvedType.SERIALIZABLE)) {
  686. warnOnAddedInterface(newInterface.getName(), sourceLocation);
  687. }
  688. }
  689. public void setSuperClass(ResolvedType newSuperclass) {
  690. regenerateGenericSignatureAttribute = true;
  691. superclass = newSuperclass;
  692. // myType.addParent(typeX); // used for the attribute
  693. if (newSuperclass.getGenericType() != null) {
  694. newSuperclass = newSuperclass.getGenericType();
  695. }
  696. myGen.setSuperclassName(newSuperclass.getName()); // used in the real
  697. // class data
  698. }
  699. // public String getSuperClassname() {
  700. // return myGen.getSuperclassName();
  701. // }
  702. public ResolvedType getSuperClass() {
  703. if (superclass != null) {
  704. return superclass;
  705. }
  706. return myType.getSuperclass();
  707. }
  708. public String[] getInterfaceNames() {
  709. return myGen.getInterfaceNames();
  710. }
  711. // non-recursive, may be a bug, ha ha.
  712. private List<LazyClassGen> getClassGens() {
  713. List<LazyClassGen> ret = new ArrayList<>();
  714. ret.add(this);
  715. ret.addAll(classGens);
  716. return ret;
  717. }
  718. public List<UnwovenClassFile.ChildClass> getChildClasses(BcelWorld world) {
  719. if (classGens.isEmpty()) {
  720. return Collections.emptyList();
  721. }
  722. List<UnwovenClassFile.ChildClass> ret = new ArrayList<>();
  723. for (LazyClassGen clazz : classGens) {
  724. byte[] bytes = clazz.getJavaClass(world).getBytes();
  725. String name = clazz.getName();
  726. int index = name.lastIndexOf('$');
  727. // XXX this could be bad, check use of dollar signs.
  728. name = name.substring(index + 1);
  729. ret.add(new UnwovenClassFile.ChildClass(name, bytes));
  730. }
  731. return ret;
  732. }
  733. @Override
  734. public String toString() {
  735. return toShortString();
  736. }
  737. public String toShortString() {
  738. String s = org.aspectj.apache.bcel.classfile.Utility.accessToString(myGen.getModifiers(), true);
  739. if (!s.equals("")) {
  740. s += " ";
  741. }
  742. s += org.aspectj.apache.bcel.classfile.Utility.classOrInterface(myGen.getModifiers());
  743. s += " ";
  744. s += myGen.getClassName();
  745. return s;
  746. }
  747. public String toLongString() {
  748. ByteArrayOutputStream s = new ByteArrayOutputStream();
  749. print(new PrintStream(s));
  750. return new String(s.toByteArray());
  751. }
  752. public void print() {
  753. print(System.out);
  754. }
  755. public void print(PrintStream out) {
  756. List<LazyClassGen> classGens = getClassGens();
  757. for (Iterator<LazyClassGen> iter = classGens.iterator(); iter.hasNext();) {
  758. LazyClassGen element = iter.next();
  759. element.printOne(out);
  760. if (iter.hasNext()) {
  761. out.println();
  762. }
  763. }
  764. }
  765. private void printOne(PrintStream out) {
  766. out.print(toShortString());
  767. out.print(" extends ");
  768. out.print(org.aspectj.apache.bcel.classfile.Utility.compactClassName(myGen.getSuperclassName(), false));
  769. int size = myGen.getInterfaces().length;
  770. if (size > 0) {
  771. out.print(" implements ");
  772. for (int i = 0; i < size; i++) {
  773. out.print(myGen.getInterfaceNames()[i]);
  774. if (i < size - 1) {
  775. out.print(", ");
  776. }
  777. }
  778. }
  779. out.print(":");
  780. out.println();
  781. // XXX make sure to pass types correctly around, so this doesn't happen.
  782. if (myType != null) {
  783. myType.printWackyStuff(out);
  784. }
  785. Field[] fields = myGen.getFields();
  786. for (Field field : fields) {
  787. out.print(" ");
  788. out.println(field);
  789. }
  790. List<LazyMethodGen> methodGens = getMethodGens();
  791. for (Iterator<LazyMethodGen> iter = methodGens.iterator(); iter.hasNext();) {
  792. LazyMethodGen gen = iter.next();
  793. // we skip empty clinits
  794. if (isEmptyClinit(gen)) {
  795. continue;
  796. }
  797. gen.print(out, (myType != null ? myType.getWeaverVersionAttribute() : WeaverVersionInfo.UNKNOWN));
  798. if (iter.hasNext()) {
  799. out.println();
  800. }
  801. }
  802. // out.println(" ATTRIBS: " + Arrays.asList(myGen.getAttributes()));
  803. out.println("end " + toShortString());
  804. }
  805. private boolean isEmptyClinit(LazyMethodGen gen) {
  806. if (!gen.getName().equals("<clinit>")) {
  807. return false;
  808. }
  809. // System.err.println("checking clinig: " + gen);
  810. InstructionHandle start = gen.getBody().getStart();
  811. while (start != null) {
  812. if (Range.isRangeHandle(start) || (start.getInstruction().opcode == Constants.RETURN)) {
  813. start = start.getNext();
  814. } else {
  815. return false;
  816. }
  817. }
  818. return true;
  819. }
  820. public ConstantPool getConstantPool() {
  821. return cp;
  822. }
  823. public String getName() {
  824. return myGen.getClassName();
  825. }
  826. public boolean isWoven() {
  827. return myType.getWeaverState() != null;
  828. }
  829. public boolean isReweavable() {
  830. if (myType.getWeaverState() == null) {
  831. return true;
  832. }
  833. return myType.getWeaverState().isReweavable();
  834. }
  835. public Set<String> getAspectsAffectingType() {
  836. if (myType.getWeaverState() == null) {
  837. return null;
  838. }
  839. return myType.getWeaverState().getAspectsAffectingType();
  840. }
  841. public WeaverStateInfo getOrCreateWeaverStateInfo(boolean inReweavableMode) {
  842. WeaverStateInfo ret = myType.getWeaverState();
  843. if (ret != null) {
  844. return ret;
  845. }
  846. ret = new WeaverStateInfo(inReweavableMode);
  847. myType.setWeaverState(ret);
  848. return ret;
  849. }
  850. public InstructionFactory getFactory() {
  851. return fact;
  852. }
  853. public LazyMethodGen getStaticInitializer() {
  854. for (LazyMethodGen gen : methodGens) {
  855. // OPTIMIZE persist kind of member into the gen object? for clinit
  856. if (gen.getName().equals("<clinit>")) {
  857. return gen;
  858. }
  859. }
  860. LazyMethodGen clinit = new LazyMethodGen(Modifier.STATIC, Type.VOID, "<clinit>", Type.NO_ARGS, NO_STRINGS, this);
  861. clinit.getBody().insert(InstructionConstants.RETURN);
  862. methodGens.add(clinit);
  863. return clinit;
  864. }
  865. /**
  866. * Retrieve the ajc$preClinit method - this method captures any initialization AspectJ wants to ensure happens in a class. It is
  867. * called from the static initializer. Maintaining this separation enables overweaving to ignore join points added due to
  868. * earlier weaves. If the ajc$preClinit method cannot be found, it is created and a call to it is placed in the real static
  869. * initializer (the call is placed at the start of the static initializer).
  870. *
  871. * @return the LazyMethodGen representing the ajc$ clinit
  872. */
  873. public LazyMethodGen getAjcPreClinit() {
  874. if (this.isInterface()) {
  875. throw new IllegalStateException();
  876. }
  877. for (LazyMethodGen methodGen : methodGens) {
  878. if (methodGen.getName().equals(NameMangler.AJC_PRE_CLINIT_NAME)) {
  879. return methodGen;
  880. }
  881. }
  882. LazyMethodGen ajcPreClinit = new LazyMethodGen(Modifier.PRIVATE | Modifier.STATIC, Type.VOID,
  883. NameMangler.AJC_PRE_CLINIT_NAME, Type.NO_ARGS, NO_STRINGS, this);
  884. ajcPreClinit.getBody().insert(InstructionConstants.RETURN);
  885. methodGens.add(ajcPreClinit);
  886. InstructionList clinitBody = getStaticInitializer().getBody();
  887. clinitBody.insert(Utility.createInvoke(fact, ajcPreClinit));
  888. if (serialVersionUIDRequiresInitialization) {
  889. InstructionList il = new InstructionList();
  890. il.append(InstructionFactory.PUSH(getConstantPool(), calculatedSerialVersionUID));
  891. il.append(getFactory().createFieldAccess(getClassName(), "serialVersionUID", BasicType.LONG,
  892. Constants.PUTSTATIC));
  893. clinitBody.insert(il);
  894. }
  895. return ajcPreClinit;
  896. }
  897. /**
  898. * factory method for building multiple extended clinit methods. Constructs a new clinit method that invokes the previous one
  899. * and then returns it. The index is used as a name suffix.
  900. *
  901. * @param previousPreClinit
  902. * @param i
  903. */
  904. public LazyMethodGen createExtendedAjcPreClinit(LazyMethodGen previousPreClinit, int i) {
  905. LazyMethodGen ajcPreClinit = new LazyMethodGen(Modifier.PRIVATE | Modifier.STATIC, Type.VOID,
  906. NameMangler.AJC_PRE_CLINIT_NAME + i, Type.NO_ARGS, NO_STRINGS, this);
  907. ajcPreClinit.getBody().insert(InstructionConstants.RETURN);
  908. methodGens.add(ajcPreClinit);
  909. previousPreClinit.getBody().insert(Utility.createInvoke(fact, ajcPreClinit));
  910. return ajcPreClinit;
  911. }
  912. //
  913. // reflective thisJoinPoint support
  914. private Map<BcelShadow, Field> tjpFields = new HashMap<>();
  915. Map<CacheKey, Field> annotationCachingFieldCache = new HashMap<>();
  916. private int tjpFieldsCounter = -1; // -1 means not yet initialized
  917. private int annoFieldsCounter = 0;
  918. public static final ObjectType proceedingTjpType = new ObjectType("org.aspectj.lang.ProceedingJoinPoint");
  919. public static final ObjectType tjpType = new ObjectType("org.aspectj.lang.JoinPoint");
  920. public static final ObjectType staticTjpType = new ObjectType("org.aspectj.lang.JoinPoint$StaticPart");
  921. public static final ObjectType typeForAnnotation = new ObjectType("java.lang.annotation.Annotation");
  922. public static final ObjectType enclosingStaticTjpType = new ObjectType("org.aspectj.lang.JoinPoint$EnclosingStaticPart");
  923. private static final ObjectType sigType = new ObjectType("org.aspectj.lang.Signature");
  924. // private static final ObjectType slType =
  925. // new ObjectType("org.aspectj.lang.reflect.SourceLocation");
  926. private static final ObjectType factoryType = new ObjectType("org.aspectj.runtime.reflect.Factory");
  927. private static final ObjectType classType = new ObjectType("java.lang.Class");
  928. public Field getTjpField(BcelShadow shadow, final boolean isEnclosingJp) {
  929. Field tjpField = tjpFields.get(shadow);
  930. if (tjpField != null) {
  931. return tjpField;
  932. }
  933. int modifiers = Modifier.STATIC;
  934. // J9: Can't always be final on Java 9 because it is set outside of clinit
  935. // But must be final in interface
  936. if (shadow.getEnclosingClass().isInterface()) {
  937. modifiers |= Modifier.FINAL;
  938. }
  939. // XXX - Do we ever inline before or after advice? If we do, then we
  940. // better include them in the check below. (or just change it to
  941. // shadow.getEnclosingMethod().getCanInline())
  942. // If the enclosing method is around advice, we could inline the join
  943. // point that has led to this shadow. If we do that then the TJP we are
  944. // creating here must be PUBLIC so it is visible to the type in which the
  945. // advice is inlined. (PR71377)
  946. LazyMethodGen encMethod = shadow.getEnclosingMethod();
  947. boolean shadowIsInAroundAdvice = false;
  948. if (encMethod != null && encMethod.getName().startsWith(NameMangler.PREFIX + "around")) {
  949. shadowIsInAroundAdvice = true;
  950. }
  951. if (getType().isInterface() || shadowIsInAroundAdvice) {
  952. modifiers |= Modifier.PUBLIC;
  953. } else {
  954. modifiers |= Modifier.PRIVATE;
  955. }
  956. ObjectType jpType = null;
  957. // Did not have different static joinpoint types in 1.2
  958. if (world.isTargettingAspectJRuntime12()) {
  959. jpType = staticTjpType;
  960. } else {
  961. jpType = isEnclosingJp ? enclosingStaticTjpType : staticTjpType;
  962. }
  963. if (tjpFieldsCounter == -1) {
  964. // not yet initialized, do it now
  965. if (!world.isOverWeaving()) {
  966. tjpFieldsCounter = 0;
  967. } else {
  968. List<BcelField> existingFields = getFieldGens();
  969. if (existingFields == null) {
  970. tjpFieldsCounter = 0;
  971. } else {
  972. BcelField lastField = null;
  973. // OPTIMIZE: go from last to first?
  974. for (BcelField field : existingFields) {
  975. if (field.getName().startsWith("ajc$tjp_")) {
  976. lastField = field;
  977. }
  978. }
  979. if (lastField == null) {
  980. tjpFieldsCounter = 0;
  981. } else {
  982. tjpFieldsCounter = Integer.parseInt(lastField.getName().substring(8)) + 1;
  983. // System.out.println("tjp counter starting at " + tjpFieldsCounter);
  984. }
  985. }
  986. }
  987. }
  988. if (!isInterface() && world.isTransientTjpFields()) {
  989. modifiers|=Modifier.TRANSIENT;
  990. }
  991. FieldGen fGen = new FieldGen(modifiers, jpType, "ajc$tjp_" + tjpFieldsCounter++, getConstantPool());
  992. addField(fGen);
  993. tjpField = fGen.getField();
  994. tjpFields.put(shadow, tjpField);
  995. return tjpField;
  996. }
  997. /**
  998. * Create a field in the type containing the shadow where the annotation retrieved during binding can be stored - for later fast
  999. * access.
  1000. *
  1001. * @param shadow the shadow at which the @annotation result is being cached
  1002. * @return a field
  1003. */
  1004. public Field getAnnotationCachingField(BcelShadow shadow, ResolvedType toType, boolean isWithin) {
  1005. // Multiple annotation types at a shadow. A different field would be required for each
  1006. CacheKey cacheKey = new CacheKey(shadow, toType, isWithin);
  1007. Field field = annotationCachingFieldCache.get(cacheKey);
  1008. // System.out.println(field + " for shadow " + shadow);
  1009. if (field == null) {
  1010. // private static Annotation ajc$anno$<nnn>
  1011. StringBuilder sb = new StringBuilder();
  1012. sb.append(NameMangler.ANNOTATION_CACHE_FIELD_NAME);
  1013. sb.append(annoFieldsCounter++);
  1014. FieldGen annotationCacheField = new FieldGen(Modifier.PRIVATE | Modifier.STATIC, typeForAnnotation, sb.toString(), cp);
  1015. addField(annotationCacheField);
  1016. field = annotationCacheField.getField();
  1017. annotationCachingFieldCache.put(cacheKey, field);
  1018. }
  1019. return field;
  1020. }
  1021. static class CacheKey {
  1022. private Object key;
  1023. private ResolvedType annotationType;
  1024. // If the annotation is being accessed via @annotation on a shadow then we can use the shadows toString() (so two shadows
  1025. // the same share a variable), but if it is @withincode() or @within() we can't share them (as the shadows may look the same
  1026. // but be occurring 'within' different things). In the within cases we continue to use the shadow itself as the key.
  1027. CacheKey(BcelShadow shadow, ResolvedType annotationType, boolean isWithin) {
  1028. this.key = isWithin ? shadow : shadow.toString();
  1029. this.annotationType = annotationType;
  1030. }
  1031. @Override
  1032. public int hashCode() {
  1033. return key.hashCode() * 37 + annotationType.hashCode();
  1034. }
  1035. @Override
  1036. public boolean equals(Object other) {
  1037. if (!(other instanceof CacheKey)) {
  1038. return false;
  1039. }
  1040. CacheKey oCacheKey = (CacheKey) other;
  1041. return key.equals(oCacheKey.key) && annotationType.equals(oCacheKey.annotationType);
  1042. }
  1043. }
  1044. // FIXME ATAJ needed only for slow Aspects.aspectOf - keep or remove
  1045. // private void addAjClassField() {
  1046. // // Andy: Why build it again??
  1047. // Field ajClassField = new FieldGen(
  1048. // Modifier.PRIVATE | Modifier.FINAL | Modifier.STATIC,
  1049. // classType,
  1050. // "aj$class",
  1051. // getConstantPool()).getField();
  1052. // addField(ajClassField);
  1053. //
  1054. // InstructionList il = new InstructionList();
  1055. // il.append(new PUSH(getConstantPool(), getClassName()));
  1056. // il.append(fact.createInvoke("java.lang.Class", "forName", classType,
  1057. // new Type[] {Type.STRING}, Constants.INVOKESTATIC));
  1058. // il.append(fact.createFieldAccess(getClassName(), ajClassField.getName(),
  1059. // classType, Constants.PUTSTATIC));
  1060. //
  1061. // getStaticInitializer().getBody().insert(il);
  1062. // }
  1063. private void addAjcInitializers() {
  1064. if (tjpFields.size() == 0 && !serialVersionUIDRequiresInitialization) {
  1065. return;
  1066. }
  1067. InstructionList[] il = initializeAllTjps();
  1068. LazyMethodGen prevMethod;
  1069. LazyMethodGen nextMethod = null;
  1070. if (this.isInterface()) { // Cannot sneak stuff into another static method in an interface
  1071. prevMethod = getStaticInitializer();
  1072. } else {
  1073. prevMethod = getAjcPreClinit();
  1074. }
  1075. for (int counter = 1; counter <= il.length; counter++) {
  1076. if (il.length > counter) {
  1077. nextMethod = createExtendedAjcPreClinit(prevMethod, counter);
  1078. }
  1079. prevMethod.getBody().insert(il[counter - 1]);
  1080. prevMethod = nextMethod;
  1081. }
  1082. }
  1083. private InstructionList initInstructionList() {
  1084. InstructionList list = new InstructionList();
  1085. InstructionFactory fact = getFactory();
  1086. // make a new factory
  1087. list.append(fact.createNew(factoryType));
  1088. list.append(InstructionFactory.createDup(1));
  1089. list.append(InstructionFactory.PUSH(getConstantPool(), getFileName()));
  1090. // load the current Class object
  1091. // XXX check that this works correctly for inners/anonymous
  1092. list.append(fact.PUSHCLASS(cp, myGen.getClassName()));
  1093. // XXX do we need to worry about the fact the theorectically this could
  1094. // throw
  1095. // a ClassNotFoundException
  1096. list.append(fact.createInvoke(factoryType.getClassName(), "<init>", Type.VOID, new Type[] { Type.STRING, classType },
  1097. Constants.INVOKESPECIAL));
  1098. list.append(InstructionFactory.createStore(factoryType, 0));
  1099. return list;
  1100. }
  1101. private InstructionList[] initializeAllTjps() {
  1102. Vector<InstructionList> lists = new Vector<>();
  1103. InstructionList list = initInstructionList();
  1104. lists.add(list);
  1105. List<Map.Entry<BcelShadow, Field>> entries = new ArrayList<>(tjpFields.entrySet());
  1106. entries.sort(new Comparator<Map.Entry<BcelShadow, Field>>() {
  1107. @Override
  1108. public int compare(Map.Entry<BcelShadow, Field> a, Map.Entry<BcelShadow, Field> b) {
  1109. return (a.getValue()).getName().compareTo((b.getValue()).getName());
  1110. }
  1111. });
  1112. long estimatedSize = 0;
  1113. for (Map.Entry<BcelShadow, Field> entry : entries) {
  1114. if (estimatedSize > Constants.MAX_CODE_SIZE) {
  1115. estimatedSize = 0;
  1116. list = initInstructionList();
  1117. lists.add(list);
  1118. }
  1119. estimatedSize += entry.getValue().getSignature().getBytes().length;
  1120. initializeTjp(fact, list, entry.getValue(), entry.getKey());
  1121. }
  1122. InstructionList listArrayModel[] = new InstructionList[1];
  1123. return lists.toArray(listArrayModel);
  1124. }
  1125. private void initializeTjp(InstructionFactory fact, InstructionList list, Field field, BcelShadow shadow) {
  1126. if (world.getTargetAspectjRuntimeLevel() == RuntimeVersion.V1_9) {
  1127. initializeTjpOptimal(fact, list, field, shadow);
  1128. return;
  1129. }
  1130. boolean fastSJP = false;
  1131. // avoid fast SJP if it is for an enclosing joinpoint
  1132. boolean isFastSJPAvailable = shadow.getWorld().isTargettingRuntime1_6_10()
  1133. && !enclosingStaticTjpType.equals(field.getType());
  1134. Member sig = shadow.getSignature();
  1135. // load the factory
  1136. list.append(InstructionFactory.createLoad(factoryType, 0));
  1137. // load the kind
  1138. list.append(InstructionFactory.PUSH(getConstantPool(), shadow.getKind().getName()));
  1139. // create the signature
  1140. if (world.isTargettingAspectJRuntime12() || !isFastSJPAvailable || !sig.getKind().equals(Member.METHOD)) {
  1141. list.append(InstructionFactory.createLoad(factoryType, 0));
  1142. }
  1143. String signatureMakerName = SignatureUtils.getSignatureMakerName(sig);
  1144. ObjectType signatureType = new ObjectType(SignatureUtils.getSignatureType(sig));
  1145. UnresolvedType[] exceptionTypes = null;
  1146. if (world.isTargettingAspectJRuntime12()) { // TAG:SUPPORTING12: We didn't have optimized factory methods in 1.2
  1147. list.append(InstructionFactory.PUSH(cp, SignatureUtils.getSignatureString(sig, shadow.getWorld())));
  1148. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY1,
  1149. Constants.INVOKEVIRTUAL));
  1150. } else if (sig.getKind().equals(Member.METHOD)) {
  1151. BcelWorld w = shadow.getWorld();
  1152. // For methods, push the parts of the signature on.
  1153. list.append(InstructionFactory.PUSH(cp, makeString(sig.getModifiers(w))));
  1154. list.append(InstructionFactory.PUSH(cp, sig.getName()));
  1155. list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
  1156. list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterTypes())));
  1157. list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterNames(w))));
  1158. exceptionTypes = sig.getExceptions(w);
  1159. if (isFastSJPAvailable && exceptionTypes.length == 0) {
  1160. fastSJP = true;
  1161. } else {
  1162. list.append(InstructionFactory.PUSH(cp, makeString(exceptionTypes)));
  1163. }
  1164. list.append(InstructionFactory.PUSH(cp, makeString(sig.getReturnType())));
  1165. // And generate a call to the variant of makeMethodSig() that takes the strings
  1166. if (isFastSJPAvailable) {
  1167. fastSJP = true;
  1168. } else {
  1169. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY7,
  1170. Constants.INVOKEVIRTUAL));
  1171. }
  1172. } else if (sig.getKind().equals(Member.MONITORENTER)) {
  1173. list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
  1174. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY1,
  1175. Constants.INVOKEVIRTUAL));
  1176. } else if (sig.getKind().equals(Member.MONITOREXIT)) {
  1177. list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
  1178. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY1,
  1179. Constants.INVOKEVIRTUAL));
  1180. } else if (sig.getKind().equals(Member.HANDLER)) {
  1181. BcelWorld w = shadow.getWorld();
  1182. list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
  1183. list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterTypes())));
  1184. list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterNames(w))));
  1185. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY3,
  1186. Constants.INVOKEVIRTUAL));
  1187. } else if (sig.getKind().equals(Member.CONSTRUCTOR)) {
  1188. BcelWorld w = shadow.getWorld();
  1189. if (w.isJoinpointArrayConstructionEnabled() && sig.getDeclaringType().isArray()) {
  1190. // its the magical new jp
  1191. list.append(InstructionFactory.PUSH(cp, makeString(Modifier.PUBLIC)));
  1192. list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
  1193. list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterTypes())));
  1194. list.append(InstructionFactory.PUSH(cp, "")); // sig.getParameterNames?
  1195. list.append(InstructionFactory.PUSH(cp, ""));// sig.getExceptions?
  1196. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY5,
  1197. Constants.INVOKEVIRTUAL));
  1198. } else {
  1199. list.append(InstructionFactory.PUSH(cp, makeString(sig.getModifiers(w))));
  1200. list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
  1201. list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterTypes())));
  1202. list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterNames(w))));
  1203. list.append(InstructionFactory.PUSH(cp, makeString(sig.getExceptions(w))));
  1204. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY5,
  1205. Constants.INVOKEVIRTUAL));
  1206. }
  1207. } else if (sig.getKind().equals(Member.FIELD)) {
  1208. BcelWorld w = shadow.getWorld();
  1209. list.append(InstructionFactory.PUSH(cp, makeString(sig.getModifiers(w))));
  1210. list.append(InstructionFactory.PUSH(cp, sig.getName()));
  1211. // see pr227401
  1212. UnresolvedType dType = sig.getDeclaringType();
  1213. if (dType.getTypekind() == TypeKind.PARAMETERIZED || dType.getTypekind() == TypeKind.GENERIC) {
  1214. dType = sig.getDeclaringType().resolve(world).getGenericType();
  1215. }
  1216. list.append(InstructionFactory.PUSH(cp, makeString(dType)));
  1217. list.append(InstructionFactory.PUSH(cp, makeString(sig.getReturnType())));
  1218. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY4,
  1219. Constants.INVOKEVIRTUAL));
  1220. } else if (sig.getKind().equals(Member.ADVICE)) {
  1221. BcelWorld w = shadow.getWorld();
  1222. list.append(InstructionFactory.PUSH(cp, makeString(sig.getModifiers(w))));
  1223. list.append(InstructionFactory.PUSH(cp, sig.getName()));
  1224. list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
  1225. list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterTypes())));
  1226. list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterNames(w))));
  1227. list.append(InstructionFactory.PUSH(cp, makeString(sig.getExceptions(w))));
  1228. list.append(InstructionFactory.PUSH(cp, makeString((sig.getReturnType()))));
  1229. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, new Type[] { Type.STRING,
  1230. Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING }, Constants.INVOKEVIRTUAL));
  1231. } else if (sig.getKind().equals(Member.STATIC_INITIALIZATION)) {
  1232. BcelWorld w = shadow.getWorld();
  1233. list.append(InstructionFactory.PUSH(cp, makeString(sig.getModifiers(w))));
  1234. list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
  1235. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY2,
  1236. Constants.INVOKEVIRTUAL));
  1237. } else {
  1238. // TODO looks like this block is unused code
  1239. list.append(InstructionFactory.PUSH(cp, SignatureUtils.getSignatureString(sig, shadow.getWorld())));
  1240. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY1,
  1241. Constants.INVOKEVIRTUAL));
  1242. }
  1243. // XXX should load source location from shadow
  1244. list.append(Utility.createConstant(fact, shadow.getSourceLine()));
  1245. final String factoryMethod;
  1246. // TAG:SUPPORTING12: We didn't have makeESJP() in 1.2
  1247. if (world.isTargettingAspectJRuntime12()) {
  1248. list.append(fact.createInvoke(factoryType.getClassName(), "makeSJP", staticTjpType, new Type[] { Type.STRING, sigType,
  1249. Type.INT }, Constants.INVOKEVIRTUAL));
  1250. // put it in the field
  1251. list.append(fact.createFieldAccess(getClassName(), field.getName(), staticTjpType, Constants.PUTSTATIC));
  1252. } else {
  1253. if (staticTjpType.equals(field.getType())) {
  1254. factoryMethod = "makeSJP";
  1255. } else if (enclosingStaticTjpType.equals(field.getType())) {
  1256. factoryMethod = "makeESJP";
  1257. } else {
  1258. throw new Error("should not happen");
  1259. }
  1260. if (fastSJP) {
  1261. if (exceptionTypes != null && exceptionTypes.length != 0) {
  1262. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(), ARRAY_8STRING_INT,
  1263. Constants.INVOKEVIRTUAL));
  1264. } else {
  1265. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(), ARRAY_7STRING_INT,
  1266. Constants.INVOKEVIRTUAL));
  1267. }
  1268. } else {
  1269. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(), new Type[] { Type.STRING,
  1270. sigType, Type.INT }, Constants.INVOKEVIRTUAL));
  1271. }
  1272. // put it in the field
  1273. list.append(fact.createFieldAccess(getClassName(), field.getName(), field.getType(), Constants.PUTSTATIC));
  1274. }
  1275. }
  1276. public String getFactoryMethod(Field field, BcelShadow shadow) {
  1277. StringBuilder b = new StringBuilder();
  1278. b.append("make");
  1279. MemberKind kind = shadow.getSignature().getKind();
  1280. if (kind.equals(Member.METHOD)) {
  1281. b.append("Method");
  1282. } else if (kind.equals(Member.CONSTRUCTOR)) {
  1283. b.append("Constructor");
  1284. } else if (kind.equals(Member.HANDLER)) {
  1285. b.append("CatchClause");
  1286. } else if (kind.equals(Member.FIELD)) {
  1287. b.append("Field");
  1288. } else if (kind.equals(Member.STATIC_INITIALIZATION)) {
  1289. b.append("Initializer");
  1290. } else if (kind.equals(Member.MONITORENTER)) {
  1291. b.append("Lock");
  1292. } else if (kind.equals(Member.MONITOREXIT)) {
  1293. b.append("Unlock");
  1294. } else if (kind.equals(Member.ADVICE)) {
  1295. b.append("Advice");
  1296. } else {
  1297. throw new IllegalStateException(kind.toString());
  1298. }
  1299. if (staticTjpType.equals(field.getType())) {
  1300. b.append("SJP");
  1301. } else if (enclosingStaticTjpType.equals(field.getType())) {
  1302. b.append("ESJP");
  1303. }
  1304. return b.toString();
  1305. }
  1306. /**
  1307. * Generate optimal joinpoint initialization code.
  1308. *
  1309. * As of version 1.9.1 the runtime includes new factory methods for joinpoints that take classes, not strings
  1310. * and using them requires different code generation. Using these instead of the old ones means we can avoid
  1311. * deferred classloading for these types. By using the LDC instruction that loads classes, it also means
  1312. * anything modifying woven code and changing type names will also pick up on these references.
  1313. */
  1314. private void initializeTjpOptimal(InstructionFactory fact, InstructionList list, Field field, BcelShadow shadow) {
  1315. list.append(InstructionFactory.createLoad(factoryType, 0));
  1316. pushString(list, shadow.getKind().getName());
  1317. String factoryMethod = getFactoryMethod(field, shadow);
  1318. Member sig = shadow.getSignature();
  1319. BcelWorld w = shadow.getWorld();
  1320. if (sig.getKind().equals(Member.METHOD)) {
  1321. pushInt(list, sig.getModifiers(w));
  1322. pushString(list, sig.getName());
  1323. pushClass(list, sig.getDeclaringType());
  1324. pushClasses(list, sig.getParameterTypes());
  1325. pushStrings(list, sig.getParameterNames(w));
  1326. pushClasses(list, sig.getExceptions(w));
  1327. pushClass(list, sig.getReturnType());
  1328. pushInt(list, shadow.getSourceLine());
  1329. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
  1330. PARAMSIGNATURE_MAKESJP_METHOD, Constants.INVOKEVIRTUAL));
  1331. } else if (sig.getKind().equals(Member.CONSTRUCTOR)) {
  1332. if (w.isJoinpointArrayConstructionEnabled() && sig.getDeclaringType().isArray()) {
  1333. pushInt(list, Modifier.PUBLIC);
  1334. pushClass(list, sig.getDeclaringType());
  1335. pushClasses(list, sig.getParameterTypes());
  1336. pushStrings(list, null);
  1337. pushClasses(list, null);
  1338. } else {
  1339. pushInt(list, sig.getModifiers(w));
  1340. pushClass(list, sig.getDeclaringType());
  1341. pushClasses(list, sig.getParameterTypes());
  1342. pushStrings(list, sig.getParameterNames(w));
  1343. pushClasses(list, sig.getExceptions(w));
  1344. }
  1345. pushInt(list, shadow.getSourceLine());
  1346. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
  1347. PARAMSIGNATURE_MAKESJP_CONSTRUCTOR, Constants.INVOKEVIRTUAL));
  1348. } else if (sig.getKind().equals(Member.HANDLER)) {
  1349. pushClass(list, sig.getDeclaringType());
  1350. pushClass(list, sig.getParameterTypes()[0]);
  1351. String pname = null;
  1352. String[] pnames = sig.getParameterNames(w);
  1353. if (pnames != null && pnames.length>0) {
  1354. pname = pnames[0];
  1355. }
  1356. pushString(list, pname);
  1357. pushInt(list, shadow.getSourceLine());
  1358. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
  1359. PARAMSIGNATURE_MAKESJP_CATCHCLAUSE, Constants.INVOKEVIRTUAL));
  1360. } else if (sig.getKind().equals(Member.FIELD)) {
  1361. pushInt(list, sig.getModifiers(w));
  1362. pushString(list, sig.getName());
  1363. // see pr227401
  1364. UnresolvedType dType = sig.getDeclaringType();
  1365. if (dType.getTypekind() == TypeKind.PARAMETERIZED || dType.getTypekind() == TypeKind.GENERIC) {
  1366. dType = sig.getDeclaringType().resolve(world).getGenericType();
  1367. }
  1368. pushClass(list, dType);
  1369. pushClass(list, sig.getReturnType());
  1370. pushInt(list,shadow.getSourceLine());
  1371. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
  1372. PARAMSIGNATURE_MAKESJP_FIELD, Constants.INVOKEVIRTUAL));
  1373. } else if (sig.getKind().equals(Member.STATIC_INITIALIZATION)) {
  1374. pushInt(list, sig.getModifiers(w));
  1375. pushClass(list, sig.getDeclaringType());
  1376. pushInt(list, shadow.getSourceLine());
  1377. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
  1378. PARAMSIGNATURE_MAKESJP_INITIALIZER, Constants.INVOKEVIRTUAL));
  1379. } else if (sig.getKind().equals(Member.MONITORENTER)) {
  1380. pushClass(list, sig.getDeclaringType());
  1381. pushInt(list, shadow.getSourceLine());
  1382. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
  1383. PARAMSIGNATURE_MAKESJP_MONITOR, Constants.INVOKEVIRTUAL));
  1384. } else if (sig.getKind().equals(Member.MONITOREXIT)) {
  1385. pushClass(list, sig.getDeclaringType());
  1386. pushInt(list, shadow.getSourceLine());
  1387. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
  1388. PARAMSIGNATURE_MAKESJP_MONITOR, Constants.INVOKEVIRTUAL));
  1389. } else if (sig.getKind().equals(Member.ADVICE)) {
  1390. pushInt(list, sig.getModifiers(w));
  1391. pushString(list, sig.getName());
  1392. pushClass(list, sig.getDeclaringType());
  1393. pushClasses(list, sig.getParameterTypes());
  1394. pushStrings(list, sig.getParameterNames(w));
  1395. pushClasses(list, sig.getExceptions(w));
  1396. pushClass(list, sig.getReturnType());
  1397. pushInt(list, shadow.getSourceLine());
  1398. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
  1399. PARAMSIGNATURE_MAKESJP_ADVICE, Constants.INVOKEVIRTUAL));
  1400. } else {
  1401. throw new IllegalStateException("not sure what to do: "+shadow);
  1402. }
  1403. list.append(fact.createFieldAccess(getClassName(), field.getName(), field.getType(), Constants.PUTSTATIC));
  1404. }
  1405. private void pushStrings(InstructionList list, String[] strings) {
  1406. // Build an array loaded with the strings
  1407. if (strings == null || strings.length == 0) {
  1408. list.append(InstructionFactory.ACONST_NULL);
  1409. } else {
  1410. list.append(InstructionFactory.PUSH(cp, strings.length));
  1411. list.append(fact.createNewArray(Type.STRING, (short)1));
  1412. for (int s=0;s<strings.length;s++) {
  1413. list.append(InstructionFactory.DUP);
  1414. list.append(InstructionFactory.PUSH(cp, s));
  1415. list.append(InstructionFactory.PUSH(cp, strings[s]));
  1416. list.append(InstructionFactory.AASTORE);
  1417. }
  1418. }
  1419. }
  1420. private void pushClass(InstructionList list, UnresolvedType type) {
  1421. if (type.isPrimitiveType()) {
  1422. if (type.getSignature().equals("I")) {
  1423. list.append(fact.createGetStatic("java/lang/Integer","TYPE", Type.CLASS));
  1424. } else if (type.getSignature().equals("D")) {
  1425. list.append(fact.createGetStatic("java/lang/Double","TYPE", Type.CLASS));
  1426. } else if (type.getSignature().equals("S")) {
  1427. list.append(fact.createGetStatic("java/lang/Short","TYPE", Type.CLASS));
  1428. } else if (type.getSignature().equals("J")) {
  1429. list.append(fact.createGetStatic("java/lang/Long","TYPE", Type.CLASS));
  1430. } else if (type.getSignature().equals("F")) {
  1431. list.append(fact.createGetStatic("java/lang/Float","TYPE", Type.CLASS));
  1432. } else if (type.getSignature().equals("C")) {
  1433. list.append(fact.createGetStatic("java/lang/Character","TYPE", Type.CLASS));
  1434. } else if (type.getSignature().equals("B")) {
  1435. list.append(fact.createGetStatic("java/lang/Byte","TYPE", Type.CLASS));
  1436. } else if (type.getSignature().equals("Z")) {
  1437. list.append(fact.createGetStatic("java/lang/Boolean","TYPE", Type.CLASS));
  1438. } else if (type.getSignature().equals("V")) {
  1439. list.append(InstructionFactory.ACONST_NULL);
  1440. }
  1441. return;
  1442. }
  1443. String classString = makeLdcClassString(type);
  1444. if (classString == null) {
  1445. list.append(InstructionFactory.ACONST_NULL);
  1446. } else {
  1447. list.append(fact.PUSHCLASS(cp, classString));
  1448. }
  1449. }
  1450. private void pushClasses(InstructionList list, UnresolvedType[] types) {
  1451. // Build an array loaded with the class objects
  1452. if (types == null || types.length == 0) {
  1453. list.append(InstructionFactory.ACONST_NULL);
  1454. } else {
  1455. list.append(InstructionFactory.PUSH(cp, types.length));
  1456. list.append(fact.createNewArray(Type.CLASS, (short)1));
  1457. for (int t=0;t<types.length;t++) {
  1458. list.append(InstructionFactory.DUP);
  1459. list.append(InstructionFactory.PUSH(cp, t));
  1460. pushClass(list, types[t]);
  1461. list.append(InstructionFactory.AASTORE);
  1462. }
  1463. }
  1464. }
  1465. private final void pushString(InstructionList list, String string) {
  1466. list.append(InstructionFactory.PUSH(cp, string));
  1467. }
  1468. private final void pushInt(InstructionList list, int value) {
  1469. list.append(InstructionFactory.PUSH(cp, value));
  1470. }
  1471. protected String makeString(int i) {
  1472. return Integer.toString(i, 16); // ??? expensive
  1473. }
  1474. protected String makeString(UnresolvedType t) {
  1475. // this is the inverse of the odd behavior for Class.forName w/ arrays
  1476. if (t.isArray()) {
  1477. // this behavior matches the string used by the eclipse compiler for
  1478. // Foo.class literals
  1479. return t.getSignature().replace('/', '.');
  1480. } else {
  1481. if (t.isParameterizedType()) {
  1482. return t.getRawType().getName();
  1483. } else {
  1484. return t.getName();
  1485. }
  1486. }
  1487. }
  1488. protected String makeLdcClassString(UnresolvedType type) {
  1489. if (type.isVoid() || type.isPrimitiveType()) {
  1490. return null;
  1491. }
  1492. if (type.isArray()) {
  1493. return type.getSignature();
  1494. } else {
  1495. if (type.isParameterizedType()) {
  1496. type = type.getRawType();
  1497. }
  1498. String signature = type.getSignature();
  1499. if (signature.length() ==1 ) {
  1500. return signature;
  1501. }
  1502. return signature.substring(1,signature.length()-1);
  1503. }
  1504. }
  1505. protected String makeString(UnresolvedType[] types) {
  1506. if (types == null) {
  1507. return "";
  1508. }
  1509. StringBuilder buf = new StringBuilder();
  1510. for (int i = 0, len = types.length; i < len; i++) {
  1511. if (i > 0) {
  1512. buf.append(':');
  1513. }
  1514. buf.append(makeString(types[i]));
  1515. }
  1516. return buf.toString();
  1517. }
  1518. protected String makeString(String[] names) {
  1519. if (names == null) {
  1520. return "";
  1521. }
  1522. StringBuilder buf = new StringBuilder();
  1523. for (int i = 0, len = names.length; i < len; i++) {
  1524. if (i > 0) {
  1525. buf.append(':');
  1526. }
  1527. buf.append(names[i]);
  1528. }
  1529. return buf.toString();
  1530. }
  1531. public ResolvedType getType() {
  1532. if (myType == null) {
  1533. return null;
  1534. }
  1535. return myType.getResolvedTypeX();
  1536. }
  1537. public BcelObjectType getBcelObjectType() {
  1538. return myType;
  1539. }
  1540. public String getFileName() {
  1541. return myGen.getFileName();
  1542. }
  1543. // for *new* fields
  1544. private void addField(FieldGen field) {
  1545. makeSyntheticAndTransientIfNeeded(field);
  1546. BcelField bcelField = null;
  1547. if (getBcelObjectType() != null) {
  1548. bcelField = new BcelField(getBcelObjectType(), field.getField());
  1549. } else {
  1550. bcelField = new BcelField(getName(), field.getField(), world);
  1551. }
  1552. fields.add(bcelField);
  1553. // myGen.addField(field.getField());
  1554. }
  1555. private void makeSyntheticAndTransientIfNeeded(FieldGen field) {
  1556. if (field.getName().startsWith(NameMangler.PREFIX) && !field.getName().startsWith("ajc$interField$")
  1557. && !field.getName().startsWith("ajc$instance$")) {
  1558. // it's an aj added field
  1559. // first do transient
  1560. if (!field.isStatic()) {
  1561. field.setModifiers(field.getModifiers() | Constants.ACC_TRANSIENT);
  1562. }
  1563. // then do synthetic
  1564. if (getWorld().isInJava5Mode()) {
  1565. // add the synthetic modifier flag
  1566. field.setModifiers(field.getModifiers() | ACC_SYNTHETIC);
  1567. }
  1568. if (!hasSyntheticAttribute(field.getAttributes())) {
  1569. // belt and braces, do the attribute even on Java 5 in addition
  1570. // to the modifier flag
  1571. // Attribute[] oldAttrs = field.getAttributes();
  1572. // Attribute[] newAttrs = new Attribute[oldAttrs.length + 1];
  1573. // System.arraycopy(oldAttrs, 0, newAttrs, 0, oldAttrs.length);
  1574. ConstantPool cpg = myGen.getConstantPool();
  1575. int index = cpg.addUtf8("Synthetic");
  1576. Attribute synthetic = new Synthetic(index, 0, new byte[0], cpg);
  1577. field.addAttribute(synthetic);
  1578. // newAttrs[newAttrs.length - 1] = synthetic;
  1579. // field.setAttributes(newAttrs);
  1580. }
  1581. }
  1582. }
  1583. private boolean hasSyntheticAttribute(List<Attribute> attributes) {
  1584. for (Attribute attribute : attributes) {
  1585. if (attribute.getName().equals("Synthetic")) {
  1586. return true;
  1587. }
  1588. }
  1589. return false;
  1590. }
  1591. public void addField(FieldGen field, ISourceLocation sourceLocation) {
  1592. addField(field);
  1593. if (!(field.isPrivate() && (field.isStatic() || field.isTransient()))) {
  1594. errorOnAddedField(field, sourceLocation);
  1595. }
  1596. }
  1597. public String getClassName() {
  1598. return myGen.getClassName();
  1599. }
  1600. public boolean isInterface() {
  1601. return myGen.isInterface();
  1602. }
  1603. public boolean isAbstract() {
  1604. return myGen.isAbstract();
  1605. }
  1606. public LazyMethodGen getLazyMethodGen(Member m) {
  1607. return getLazyMethodGen(m.getName(), m.getSignature(), false);
  1608. }
  1609. public LazyMethodGen getLazyMethodGen(String name, String signature) {
  1610. return getLazyMethodGen(name, signature, false);
  1611. }
  1612. public LazyMethodGen getLazyMethodGen(String name, String signature, boolean allowMissing) {
  1613. for (LazyMethodGen gen : methodGens) {
  1614. if (gen.getName().equals(name) && gen.getSignature().equals(signature)) {
  1615. return gen;
  1616. }
  1617. }
  1618. if (!allowMissing) {
  1619. throw new BCException("Class " + this.getName() + " does not have a method " + name + " with signature " + signature);
  1620. }
  1621. return null;
  1622. }
  1623. public void forcePublic() {
  1624. myGen.setModifiers(Utility.makePublic(myGen.getModifiers()));
  1625. }
  1626. public boolean hasAnnotation(UnresolvedType t) {
  1627. // annotations on the real thing
  1628. AnnotationGen agens[] = myGen.getAnnotations();
  1629. if (agens == null) {
  1630. return false;
  1631. }
  1632. for (AnnotationGen gen : agens) {
  1633. if (t.equals(UnresolvedType.forSignature(gen.getTypeSignature()))) {
  1634. return true;
  1635. }
  1636. }
  1637. // annotations added during this weave
  1638. return false;
  1639. }
  1640. public void addAnnotation(AnnotationGen a) {
  1641. if (!hasAnnotation(UnresolvedType.forSignature(a.getTypeSignature()))) {
  1642. annotations.add(new AnnotationGen(a, getConstantPool(), true));
  1643. }
  1644. }
  1645. public void addAttribute(AjAttribute attribute) {
  1646. myGen.addAttribute(Utility.bcelAttribute(attribute, getConstantPool()));
  1647. }
  1648. public void addAttribute(Attribute attribute) {
  1649. myGen.addAttribute(attribute);
  1650. }
  1651. public Collection<Attribute> getAttributes() {
  1652. return myGen.getAttributes();
  1653. }
  1654. // this test is like asking:
  1655. // if
  1656. // (UnresolvedType.SERIALIZABLE.resolve(getType().getWorld()).isAssignableFrom
  1657. // (getType())) {
  1658. // only we don't do that because this forces us to find all the supertypes
  1659. // of the type,
  1660. // and if one of them is missing we fail, and it's not worth failing just to
  1661. // put out
  1662. // a warning message!
  1663. private boolean implementsSerializable(ResolvedType aType) {
  1664. if (aType.getSignature().equals(UnresolvedType.SERIALIZABLE.getSignature())) {
  1665. return true;
  1666. }
  1667. ResolvedType[] interfaces = aType.getDeclaredInterfaces();
  1668. for (ResolvedType anInterface : interfaces) {
  1669. if (anInterface.isMissing()) {
  1670. continue;
  1671. }
  1672. if (implementsSerializable(anInterface)) {
  1673. return true;
  1674. }
  1675. }
  1676. ResolvedType superType = aType.getSuperclass();
  1677. if (superType != null && !superType.isMissing()) {
  1678. return implementsSerializable(superType);
  1679. }
  1680. return false;
  1681. }
  1682. public boolean isAtLeastJava5() {
  1683. return (myGen.getMajor() >= Constants.MAJOR_1_5);
  1684. }
  1685. /**
  1686. * Return the next available field name with the specified 'prefix', e.g. for prefix 'class$' where class$0, class$1 exist then
  1687. * return class$2
  1688. */
  1689. public String allocateField(String prefix) {
  1690. int highestAllocated = -1;
  1691. List<BcelField> fs = getFieldGens();
  1692. for (BcelField field : fs) {
  1693. if (field.getName().startsWith(prefix)) {
  1694. try {
  1695. int num = Integer.parseInt(field.getName().substring(prefix.length()));
  1696. if (num > highestAllocated) {
  1697. highestAllocated = num;
  1698. }
  1699. } catch (NumberFormatException nfe) {
  1700. // something wrong with the number on the end of that
  1701. // field...
  1702. }
  1703. }
  1704. }
  1705. return prefix + Integer.toString(highestAllocated + 1);
  1706. }
  1707. }