Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

ClassLoaderWeavingAdaptor.java 40KB

19 роки тому
6 роки тому
19 роки тому
19 роки тому
19 роки тому
6 роки тому
5 роки тому
13 роки тому
6 роки тому
6 роки тому
18 роки тому
19 роки тому
6 роки тому
19 роки тому
19 роки тому
13 роки тому
6 роки тому
19 роки тому
15 роки тому
6 роки тому
15 роки тому
15 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
4 роки тому
15 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
15 роки тому
15 роки тому
15 роки тому
15 роки тому
4 роки тому
15 роки тому
11 роки тому
15 роки тому
11 роки тому
15 роки тому
13 роки тому
11 роки тому
13 роки тому
11 роки тому
13 роки тому
15 роки тому
14 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
6 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
15 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
15 роки тому
4 роки тому
15 роки тому
14 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
15 роки тому
6 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
6 роки тому
15 роки тому
14 роки тому
15 роки тому
15 роки тому
14 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
4 роки тому
15 роки тому
15 роки тому
15 роки тому
15 роки тому
15 роки тому
15 роки тому
15 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
6 роки тому
15 роки тому
6 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
6 роки тому
15 роки тому
6 роки тому
15 роки тому
14 роки тому
15 роки тому
15 роки тому
4 роки тому
15 роки тому
14 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
14 роки тому
15 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
15 роки тому
11 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
15 роки тому
4 роки тому
15 роки тому
15 роки тому
15 роки тому
6 роки тому
15 роки тому
15 роки тому
15 роки тому
4 роки тому
15 роки тому
15 роки тому
15 роки тому
4 роки тому
15 роки тому
15 роки тому
6 роки тому
15 роки тому
6 роки тому
15 роки тому
15 роки тому
15 роки тому
4 роки тому
14 роки тому
15 роки тому
15 роки тому
15 роки тому
15 роки тому
15 роки тому
15 роки тому
15 роки тому
15 роки тому
15 роки тому
15 роки тому
15 роки тому
15 роки тому
15 роки тому
6 роки тому
15 роки тому
15 роки тому
15 роки тому
6 роки тому
15 роки тому
6 роки тому
15 роки тому
14 роки тому
15 роки тому
6 роки тому
15 роки тому
6 роки тому
15 роки тому
15 роки тому
14 роки тому
15 роки тому
15 роки тому
15 роки тому
15 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
4 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
14 роки тому
15 роки тому
15 роки тому
13 роки тому
4 роки тому
5 роки тому
4 роки тому
5 роки тому
4 роки тому
5 роки тому
5 роки тому
5 роки тому
4 роки тому
5 роки тому
4 роки тому
5 роки тому
4 роки тому
5 роки тому
4 роки тому
5 роки тому
13 роки тому
5 роки тому
13 роки тому
4 роки тому
13 роки тому
5 роки тому
13 роки тому
5 роки тому
5 роки тому
4 роки тому
5 роки тому
4 роки тому
5 роки тому
14 роки тому
15 роки тому
14 роки тому
5 роки тому
4 роки тому
5 роки тому
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184
  1. /*******************************************************************************
  2. * Copyright (c) 2005, 2017 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. package org.aspectj.weaver.loadtime;
  10. import java.io.File;
  11. import java.io.IOException;
  12. import java.io.InputStream;
  13. import java.lang.reflect.Field;
  14. import java.lang.reflect.Method;
  15. import java.net.MalformedURLException;
  16. import java.net.URL;
  17. import java.security.ProtectionDomain;
  18. import java.util.ArrayList;
  19. import java.util.Enumeration;
  20. import java.util.HashMap;
  21. import java.util.HashSet;
  22. import java.util.Iterator;
  23. import java.util.LinkedList;
  24. import java.util.List;
  25. import java.util.Map;
  26. import java.util.Map.Entry;
  27. import java.util.Properties;
  28. import java.util.Set;
  29. import java.util.StringTokenizer;
  30. import org.aspectj.bridge.AbortException;
  31. import org.aspectj.bridge.Constants;
  32. import org.aspectj.bridge.MessageUtil;
  33. import org.aspectj.util.LangUtil;
  34. import org.aspectj.weaver.IUnwovenClassFile;
  35. import org.aspectj.weaver.Lint;
  36. import org.aspectj.weaver.Lint.Kind;
  37. import org.aspectj.weaver.ResolvedType;
  38. import org.aspectj.weaver.UnresolvedType;
  39. import org.aspectj.weaver.World;
  40. import org.aspectj.weaver.bcel.BcelWeakClassLoaderReference;
  41. import org.aspectj.weaver.bcel.BcelWeaver;
  42. import org.aspectj.weaver.bcel.BcelWorld;
  43. import org.aspectj.weaver.bcel.Utility;
  44. import org.aspectj.weaver.loadtime.definition.Definition;
  45. import org.aspectj.weaver.loadtime.definition.DocumentParser;
  46. import org.aspectj.weaver.ltw.LTWWorld;
  47. import org.aspectj.weaver.patterns.PatternParser;
  48. import org.aspectj.weaver.patterns.TypePattern;
  49. import org.aspectj.weaver.tools.GeneratedClassHandler;
  50. import org.aspectj.weaver.tools.Trace;
  51. import org.aspectj.weaver.tools.TraceFactory;
  52. import org.aspectj.weaver.tools.WeavingAdaptor;
  53. import org.aspectj.weaver.tools.cache.WeavedClassCache;
  54. import sun.misc.Unsafe;
  55. /**
  56. * @author Alexandre Vasseur
  57. * @author Andy Clement
  58. * @author Abraham Nevado
  59. * @author David Knibb
  60. * @author John Kew
  61. */
  62. public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
  63. private final static String AOP_XML = Constants.AOP_USER_XML + ";" + Constants.AOP_AJC_XML + ";" + Constants.AOP_OSGI_XML;
  64. private boolean initialized;
  65. private List<TypePattern> dumpTypePattern = new ArrayList<>();
  66. private boolean dumpBefore = false;
  67. private boolean dumpDirPerClassloader = false;
  68. private boolean hasExcludes = false;
  69. private List<TypePattern> excludeTypePattern = new ArrayList<>(); // anything
  70. private List<String> excludeStartsWith = new ArrayList<>(); // com.foo..*
  71. private List<String> excludeStarDotDotStar = new ArrayList<>(); // *..*CGLIB*
  72. private List<String> excludeExactName = new ArrayList<>(); // com.foo.Bar
  73. private List<String> excludeEndsWith = new ArrayList<>(); // com.foo.Bar
  74. private List<String[]> excludeSpecial = new ArrayList<>();
  75. private boolean hasIncludes = false;
  76. private List<TypePattern> includeTypePattern = new ArrayList<>();
  77. private List<String> includeStartsWith = new ArrayList<>();
  78. private List<String> includeExactName = new ArrayList<>();
  79. private boolean includeStar = false;
  80. private List<TypePattern> aspectExcludeTypePattern = new ArrayList<>();
  81. private List<String> aspectExcludeStartsWith = new ArrayList<>();
  82. private List<TypePattern> aspectIncludeTypePattern = new ArrayList<>();
  83. private List<String> aspectIncludeStartsWith = new ArrayList<>();
  84. private StringBuffer namespace;
  85. private IWeavingContext weavingContext;
  86. private List<ConcreteAspectCodeGen> concreteAspects = new ArrayList<>();
  87. private static Trace trace = TraceFactory.getTraceFactory().getTrace(ClassLoaderWeavingAdaptor.class);
  88. public ClassLoaderWeavingAdaptor() {
  89. super();
  90. if (trace.isTraceEnabled()) {
  91. trace.enter("<init>", this);
  92. }
  93. if (trace.isTraceEnabled()) {
  94. trace.exit("<init>");
  95. }
  96. }
  97. /**
  98. * We don't need a reference to the class loader and using it during construction can cause problems with recursion. It also
  99. * makes sense to supply the weaving context during initialization to.
  100. *
  101. * @deprecated
  102. */
  103. @Deprecated
  104. public ClassLoaderWeavingAdaptor(final ClassLoader deprecatedLoader, final IWeavingContext deprecatedContext) {
  105. super();
  106. if (trace.isTraceEnabled()) {
  107. trace.enter("<init>", this, new Object[] { deprecatedLoader, deprecatedContext });
  108. }
  109. if (trace.isTraceEnabled()) {
  110. trace.exit("<init>");
  111. }
  112. }
  113. class SimpleGeneratedClassHandler implements GeneratedClassHandler {
  114. private BcelWeakClassLoaderReference loaderRef;
  115. SimpleGeneratedClassHandler(ClassLoader loader) {
  116. loaderRef = new BcelWeakClassLoaderReference(loader);
  117. }
  118. /**
  119. * Callback when we need to define a Closure in the JVM
  120. *
  121. */
  122. @Override
  123. public void acceptClass (String name, byte[] originalBytes, byte[] wovenBytes) {
  124. try {
  125. if (shouldDump(name.replace('/', '.'), false)) {
  126. dump(name, wovenBytes, false);
  127. }
  128. } catch (Throwable throwable) {
  129. throwable.printStackTrace();
  130. }
  131. if (activeProtectionDomain != null) {
  132. defineClass(loaderRef.getClassLoader(), name, wovenBytes, activeProtectionDomain);
  133. } else {
  134. defineClass(loaderRef.getClassLoader(), name, wovenBytes); // could be done lazily using the hook
  135. }
  136. }
  137. }
  138. public void initialize(final ClassLoader classLoader, IWeavingContext context) {
  139. if (initialized) {
  140. return;
  141. }
  142. boolean success = true;
  143. this.weavingContext = context;
  144. if (weavingContext == null) {
  145. weavingContext = new DefaultWeavingContext(classLoader);
  146. }
  147. createMessageHandler();
  148. this.generatedClassHandler = new SimpleGeneratedClassHandler(classLoader);
  149. List<Definition> definitions = weavingContext.getDefinitions(classLoader, this);
  150. if (definitions.isEmpty()) {
  151. disable(); // TODO maw Needed to ensure messages are flushed
  152. if (trace.isTraceEnabled()) {
  153. trace.exit("initialize", definitions);
  154. }
  155. return;
  156. }
  157. // TODO when the world works in terms of the context, we can remove the loader
  158. bcelWorld = new LTWWorld(classLoader, weavingContext, getMessageHandler(), null);
  159. weaver = new BcelWeaver(bcelWorld);
  160. // register the definitions
  161. success = registerDefinitions(weaver, classLoader, definitions);
  162. if (success) {
  163. // after adding aspects
  164. weaver.prepareForWeave();
  165. enable(); // TODO maw Needed to ensure messages are flushed
  166. success = weaveAndDefineConceteAspects();
  167. }
  168. if (success) {
  169. enable();
  170. } else {
  171. disable();
  172. bcelWorld = null;
  173. weaver = null;
  174. }
  175. if (WeavedClassCache.isEnabled()) {
  176. initializeCache(classLoader, getAspectClassNames(definitions), generatedClassHandler, getMessageHandler());
  177. }
  178. initialized = true;
  179. if (trace.isTraceEnabled()) {
  180. trace.exit("initialize", isEnabled());
  181. }
  182. }
  183. /**
  184. * Get the list of all aspects from the defintion list
  185. * @param definitions
  186. * @return
  187. */
  188. List<String> getAspectClassNames(List<Definition> definitions) {
  189. List<String> aspects = new LinkedList<>();
  190. for (Definition def : definitions) {
  191. List<String> defAspects = def.getAspectClassNames();
  192. if (defAspects != null) {
  193. aspects.addAll(defAspects);
  194. }
  195. }
  196. return aspects;
  197. }
  198. /**
  199. * Load and cache the aop.xml/properties according to the classloader visibility rules
  200. *
  201. * @param loader
  202. */
  203. List<Definition> parseDefinitions(final ClassLoader loader) {
  204. if (trace.isTraceEnabled()) {
  205. trace.enter("parseDefinitions", this);
  206. }
  207. List<Definition> definitions = new ArrayList<>();
  208. try {
  209. info("register classloader " + getClassLoaderName(loader));
  210. // TODO av underoptimized: we will parse each XML once per CL that see it
  211. // TODO av dev mode needed ? TBD -Daj5.def=...
  212. if (loader.equals(ClassLoader.getSystemClassLoader())) {
  213. String file = System.getProperty("aj5.def", null);
  214. if (file != null) {
  215. info("using (-Daj5.def) " + file);
  216. definitions.add(DocumentParser.parse((new File(file)).toURI().toURL()));
  217. }
  218. }
  219. String resourcePath = System.getProperty("org.aspectj.weaver.loadtime.configuration", AOP_XML);
  220. if (trace.isTraceEnabled()) {
  221. trace.event("parseDefinitions", this, resourcePath);
  222. }
  223. StringTokenizer st = new StringTokenizer(resourcePath, ";");
  224. while (st.hasMoreTokens()) {
  225. String nextDefinition = st.nextToken();
  226. if (nextDefinition.startsWith("file:")) {
  227. try {
  228. String fpath = new URL(nextDefinition).getFile();
  229. File configFile = new File(fpath);
  230. if (!configFile.exists()) {
  231. warn("configuration does not exist: " + nextDefinition);
  232. } else {
  233. definitions.add(DocumentParser.parse(configFile.toURI().toURL()));
  234. }
  235. } catch (MalformedURLException mue) {
  236. error("malformed definition url: " + nextDefinition);
  237. }
  238. } else {
  239. Enumeration<URL> xmls = weavingContext.getResources(nextDefinition);
  240. // System.out.println("? registerDefinitions: found-aop.xml=" + xmls.hasMoreElements() + ", loader=" + loader);
  241. Set<URL> seenBefore = new HashSet<>();
  242. while (xmls.hasMoreElements()) {
  243. URL xml = xmls.nextElement();
  244. if (trace.isTraceEnabled()) {
  245. trace.event("parseDefinitions", this, xml);
  246. }
  247. if (!seenBefore.contains(xml)) {
  248. info("using configuration " + weavingContext.getFile(xml));
  249. definitions.add(DocumentParser.parse(xml));
  250. seenBefore.add(xml);
  251. } else {
  252. debug("ignoring duplicate definition: " + xml);
  253. }
  254. }
  255. }
  256. }
  257. if (definitions.isEmpty()) {
  258. info("no configuration found. Disabling weaver for class loader " + getClassLoaderName(loader));
  259. }
  260. } catch (Exception e) {
  261. definitions.clear();
  262. warn("parse definitions failed", e);
  263. }
  264. if (trace.isTraceEnabled()) {
  265. trace.exit("parseDefinitions", definitions);
  266. }
  267. return definitions;
  268. }
  269. private boolean registerDefinitions(final BcelWeaver weaver, final ClassLoader loader, List<Definition> definitions) {
  270. if (trace.isTraceEnabled()) {
  271. trace.enter("registerDefinitions", this, definitions);
  272. }
  273. boolean success = true;
  274. try {
  275. registerOptions(weaver, loader, definitions);
  276. registerAspectExclude(weaver, loader, definitions);
  277. registerAspectInclude(weaver, loader, definitions);
  278. success = registerAspects(weaver, loader, definitions);
  279. registerIncludeExclude(weaver, loader, definitions);
  280. registerDump(weaver, loader, definitions);
  281. } catch (Exception ex) {
  282. trace.error("register definition failed", ex);
  283. success = false;
  284. warn("register definition failed", (ex instanceof AbortException) ? null : ex);
  285. }
  286. if (trace.isTraceEnabled()) {
  287. trace.exit("registerDefinitions", success);
  288. }
  289. return success;
  290. }
  291. private String getClassLoaderName(ClassLoader loader) {
  292. return weavingContext.getClassLoaderName();
  293. }
  294. /**
  295. * Configure the weaver according to the option directives TODO av - don't know if it is that good to reuse, since we only allow
  296. * a small subset of options in LTW
  297. *
  298. * @param weaver
  299. * @param loader
  300. * @param definitions
  301. */
  302. private void registerOptions(final BcelWeaver weaver, final ClassLoader loader, final List<Definition> definitions) {
  303. StringBuilder allOptions = new StringBuilder();
  304. for (Definition definition : definitions) {
  305. allOptions.append(definition.getWeaverOptions()).append(' ');
  306. }
  307. Options.WeaverOption weaverOption = Options.parse(allOptions.toString(), loader, getMessageHandler());
  308. // configure the weaver and world
  309. // AV - code duplicates AspectJBuilder.initWorldAndWeaver()
  310. World world = weaver.getWorld();
  311. setMessageHandler(weaverOption.messageHandler);
  312. world.setXlazyTjp(weaverOption.lazyTjp);
  313. world.setXHasMemberSupportEnabled(weaverOption.hasMember);
  314. world.setTiming(weaverOption.timers, true);
  315. world.setOptionalJoinpoints(weaverOption.optionalJoinpoints);
  316. world.setPinpointMode(weaverOption.pinpoint);
  317. weaver.setReweavableMode(weaverOption.notReWeavable);
  318. if (weaverOption.loadersToSkip != null && weaverOption.loadersToSkip.length() > 0) {
  319. Aj.loadersToSkip = LangUtil.anySplit(weaverOption.loadersToSkip, ",");
  320. }
  321. if (Aj.loadersToSkip != null) {
  322. MessageUtil.info(world.getMessageHandler(),"no longer creating weavers for these classloaders: "+Aj.loadersToSkip);
  323. }
  324. world.performExtraConfiguration(weaverOption.xSet);
  325. world.setXnoInline(weaverOption.noInline);
  326. // AMC - autodetect as per line below, needed for AtAjLTWTests.testLTWUnweavable
  327. world.setBehaveInJava5Way(true);
  328. world.setAddSerialVerUID(weaverOption.addSerialVersionUID);
  329. /* First load defaults */
  330. bcelWorld.getLint().loadDefaultProperties();
  331. /* Second overlay LTW defaults */
  332. bcelWorld.getLint().adviceDidNotMatch.setKind(null);
  333. /* Third load user file using -Xlintfile so that -Xlint wins */
  334. if (weaverOption.lintFile != null) {
  335. InputStream resource = null;
  336. try {
  337. resource = loader.getResourceAsStream(weaverOption.lintFile);
  338. Exception failure = null;
  339. if (resource != null) {
  340. try {
  341. Properties properties = new Properties();
  342. properties.load(resource);
  343. world.getLint().setFromProperties(properties);
  344. } catch (IOException e) {
  345. failure = e;
  346. }
  347. }
  348. if (failure != null || resource == null) {
  349. warn("Cannot access resource for -Xlintfile:" + weaverOption.lintFile, failure);
  350. // world.getMessageHandler().handleMessage(new Message(
  351. // "Cannot access resource for -Xlintfile:"+weaverOption.lintFile,
  352. // IMessage.WARNING,
  353. // failure,
  354. // null));
  355. }
  356. } finally {
  357. try {
  358. resource.close();
  359. } catch (Throwable t) {
  360. }
  361. }
  362. }
  363. /* Fourth override with -Xlint */
  364. if (weaverOption.lint != null) {
  365. if (weaverOption.lint.equals("default")) {// FIXME should be AjBuildConfig.AJLINT_DEFAULT but yetanother deps..
  366. bcelWorld.getLint().loadDefaultProperties();
  367. } else {
  368. bcelWorld.getLint().setAll(weaverOption.lint);
  369. if (weaverOption.lint.equals("ignore")) {
  370. bcelWorld.setAllLintIgnored();
  371. }
  372. }
  373. }
  374. // TODO proceedOnError option
  375. }
  376. private void registerAspectExclude(final BcelWeaver weaver, final ClassLoader loader, final List<Definition> definitions) {
  377. String fastMatchInfo = null;
  378. for (Definition definition : definitions) {
  379. for (String exclude : definition.getAspectExcludePatterns()) {
  380. TypePattern excludePattern = new PatternParser(exclude).parseTypePattern();
  381. aspectExcludeTypePattern.add(excludePattern);
  382. fastMatchInfo = looksLikeStartsWith(exclude);
  383. if (fastMatchInfo != null) {
  384. aspectExcludeStartsWith.add(fastMatchInfo);
  385. }
  386. }
  387. }
  388. }
  389. private void registerAspectInclude(final BcelWeaver weaver, final ClassLoader loader, final List<Definition> definitions) {
  390. String fastMatchInfo = null;
  391. for (Definition definition : definitions) {
  392. for (String include : definition.getAspectIncludePatterns()) {
  393. TypePattern includePattern = new PatternParser(include).parseTypePattern();
  394. aspectIncludeTypePattern.add(includePattern);
  395. fastMatchInfo = looksLikeStartsWith(include);
  396. if (fastMatchInfo != null) {
  397. aspectIncludeStartsWith.add(fastMatchInfo);
  398. }
  399. }
  400. }
  401. }
  402. protected void lint(String name, String[] infos) {
  403. Lint lint = bcelWorld.getLint();
  404. Kind kind = lint.getLintKind(name);
  405. kind.signal(infos, null, null);
  406. }
  407. @Override
  408. public String getContextId() {
  409. return weavingContext.getId();
  410. }
  411. /**
  412. * Register the aspect, following include / exclude rules
  413. *
  414. * @param weaver
  415. * @param loader
  416. * @param definitions
  417. */
  418. private boolean registerAspects(final BcelWeaver weaver, final ClassLoader loader, final List<Definition> definitions) {
  419. if (trace.isTraceEnabled()) {
  420. trace.enter("registerAspects", this, new Object[] { weaver, loader, definitions });
  421. }
  422. boolean success = true;
  423. // TODO: the exclude aspect allow to exclude aspect defined upper in the CL hierarchy - is it what we want ??
  424. // if not, review the getResource so that we track which resource is defined by which CL
  425. // iterate aspectClassNames
  426. // exclude if in any of the exclude list
  427. for (Definition definition : definitions) {
  428. for (String aspectClassName : definition.getAspectClassNames()) {
  429. if (acceptAspect(aspectClassName)) {
  430. info("register aspect " + aspectClassName);
  431. // System.err.println("? ClassLoaderWeavingAdaptor.registerAspects() aspectName=" + aspectClassName +
  432. // ", loader=" + loader + ", bundle=" + weavingContext.getClassLoaderName());
  433. String requiredType = definition.getAspectRequires(aspectClassName);
  434. if (requiredType != null) {
  435. // This aspect expresses that it requires a type to be around, otherwise it should 'switch off'
  436. ((BcelWorld) weaver.getWorld()).addAspectRequires(aspectClassName, requiredType);
  437. }
  438. String definedScope = definition.getScopeForAspect(aspectClassName);
  439. if (definedScope != null) {
  440. ((BcelWorld) weaver.getWorld()).addScopedAspect(aspectClassName, definedScope);
  441. }
  442. // ResolvedType aspect =
  443. weaver.addLibraryAspect(aspectClassName);
  444. // generate key for SC
  445. if (namespace == null) {
  446. namespace = new StringBuffer(aspectClassName);
  447. } else {
  448. namespace = namespace.append(";").append(aspectClassName);
  449. }
  450. } else {
  451. // warn("aspect excluded: " + aspectClassName);
  452. lint("aspectExcludedByConfiguration", new String[] { aspectClassName, getClassLoaderName(loader) });
  453. }
  454. }
  455. }
  456. // iterate concreteAspects
  457. // exclude if in any of the exclude list - note that the user defined name matters for that to happen
  458. for (Definition definition : definitions) {
  459. for (Definition.ConcreteAspect concreteAspect : definition.getConcreteAspects()) {
  460. if (acceptAspect(concreteAspect.name)) {
  461. info("define aspect " + concreteAspect.name);
  462. ConcreteAspectCodeGen gen = new ConcreteAspectCodeGen(concreteAspect, weaver.getWorld());
  463. if (!gen.validate()) {
  464. error("Concrete-aspect '" + concreteAspect.name + "' could not be registered");
  465. success = false;
  466. break;
  467. }
  468. ((BcelWorld) weaver.getWorld()).addSourceObjectType(Utility.makeJavaClass(concreteAspect.name, gen.getBytes()),
  469. true);
  470. concreteAspects.add(gen);
  471. weaver.addLibraryAspect(concreteAspect.name);
  472. // generate key for SC
  473. if (namespace == null) {
  474. namespace = new StringBuffer(concreteAspect.name);
  475. } else {
  476. namespace = namespace.append(";" + concreteAspect.name);
  477. }
  478. }
  479. }
  480. }
  481. /* We couldn't register one or more aspects so disable the adaptor */
  482. if (!success) {
  483. warn("failure(s) registering aspects. Disabling weaver for class loader " + getClassLoaderName(loader));
  484. }
  485. /* We didn't register any aspects so disable the adaptor */
  486. else if (namespace == null) {
  487. success = false;
  488. info("no aspects registered. Disabling weaver for class loader " + getClassLoaderName(loader));
  489. }
  490. if (trace.isTraceEnabled()) {
  491. trace.exit("registerAspects", success);
  492. }
  493. return success;
  494. }
  495. private boolean weaveAndDefineConceteAspects() {
  496. if (trace.isTraceEnabled()) {
  497. trace.enter("weaveAndDefineConceteAspects", this, concreteAspects);
  498. }
  499. boolean success = true;
  500. for (ConcreteAspectCodeGen gen : concreteAspects) {
  501. String name = gen.getClassName();
  502. byte[] bytes = gen.getBytes();
  503. try {
  504. byte[] newBytes = weaveClass(name, bytes, true);
  505. this.generatedClassHandler.acceptClass(name, bytes, newBytes);
  506. } catch (IOException ex) {
  507. trace.error("weaveAndDefineConceteAspects", ex);
  508. error("exception weaving aspect '" + name + "'", ex);
  509. }
  510. }
  511. if (trace.isTraceEnabled()) {
  512. trace.exit("weaveAndDefineConceteAspects", success);
  513. }
  514. return success;
  515. }
  516. /**
  517. * Register the include / exclude filters. We duplicate simple patterns in startWith filters that will allow faster matching
  518. * without ResolvedType
  519. *
  520. * @param weaver
  521. * @param loader
  522. * @param definitions
  523. */
  524. private void registerIncludeExclude(final BcelWeaver weaver, final ClassLoader loader, final List<Definition> definitions) {
  525. String fastMatchInfo = null;
  526. for (Definition definition : definitions) {
  527. for (String value : definition.getIncludePatterns()) {
  528. hasIncludes = true;
  529. String include = value;
  530. fastMatchInfo = looksLikeStartsWith(include);
  531. if (fastMatchInfo != null) {
  532. includeStartsWith.add(fastMatchInfo);
  533. } else if (include.equals("*")) {
  534. includeStar = true;
  535. } else if ((fastMatchInfo = looksLikeExactName(include)) != null) {
  536. includeExactName.add(fastMatchInfo);
  537. } else {
  538. TypePattern includePattern = new PatternParser(include).parseTypePattern();
  539. includeTypePattern.add(includePattern);
  540. }
  541. }
  542. for (String s : definition.getExcludePatterns()) {
  543. hasExcludes = true;
  544. String exclude = s;
  545. fastMatchInfo = looksLikeStartsWith(exclude);
  546. if (fastMatchInfo != null) {
  547. excludeStartsWith.add(fastMatchInfo);
  548. } else if ((fastMatchInfo = looksLikeStarDotDotStarExclude(exclude)) != null) {
  549. excludeStarDotDotStar.add(fastMatchInfo);
  550. } else if ((fastMatchInfo = looksLikeExactName(exclude)) != null) {
  551. excludeExactName.add(exclude);
  552. } else if ((fastMatchInfo = looksLikeEndsWith(exclude)) != null) {
  553. excludeEndsWith.add(fastMatchInfo);
  554. } else if (exclude
  555. .equals("org.codehaus.groovy..* && !org.codehaus.groovy.grails.web.servlet.mvc.SimpleGrailsController*")) {
  556. // TODO need a more sophisticated analysis here, to allow for similar situations
  557. excludeSpecial.add(new String[]{"org.codehaus.groovy.",
  558. "org.codehaus.groovy.grails.web.servlet.mvc.SimpleGrailsController"});
  559. // for the related test:
  560. // } else if (exclude.equals("testdata..* && !testdata.sub.Oran*")) {
  561. // excludeSpecial.add(new String[] { "testdata.", "testdata.sub.Oran" });
  562. } else {
  563. TypePattern excludePattern = new PatternParser(exclude).parseTypePattern();
  564. excludeTypePattern.add(excludePattern);
  565. }
  566. }
  567. }
  568. }
  569. /**
  570. * Checks if the pattern looks like "*..*XXXX*" and if so returns XXXX. This will enable fast name matching of CGLIB exclusion
  571. *
  572. */
  573. private String looksLikeStarDotDotStarExclude(String typePattern) {
  574. if (!typePattern.startsWith("*..*")) {
  575. return null;
  576. }
  577. if (!typePattern.endsWith("*")) {
  578. return null;
  579. }
  580. String subPattern = typePattern.substring(4, typePattern.length() - 1);
  581. if (hasStarDot(subPattern, 0)) {
  582. return null;
  583. }
  584. return subPattern.replace('$', '.');
  585. }
  586. /**
  587. * Checks if the pattern looks like "com.foo.Bar" - an exact name
  588. */
  589. private String looksLikeExactName(String typePattern) {
  590. if (hasSpaceAnnotationPlus(typePattern, 0) || typePattern.contains("*")) {
  591. return null;
  592. }
  593. return typePattern.replace('$', '.');
  594. }
  595. /**
  596. * Checks if the pattern looks like "*Exception"
  597. */
  598. private String looksLikeEndsWith(String typePattern) {
  599. if (typePattern.charAt(0) != '*') {
  600. return null;
  601. }
  602. if (hasSpaceAnnotationPlus(typePattern, 1) || hasStarDot(typePattern, 1)) {
  603. return null;
  604. }
  605. return typePattern.substring(1).replace('$', '.');
  606. }
  607. /**
  608. * Determine if something in the string is going to affect our ability to optimize. Checks for: ' ' '@' '+'
  609. */
  610. private boolean hasSpaceAnnotationPlus(String string, int pos) {
  611. for (int i = pos, max = string.length(); i < max; i++) {
  612. char ch = string.charAt(i);
  613. if (ch == ' ' || ch == '@' || ch == '+') {
  614. return true;
  615. }
  616. }
  617. return false;
  618. }
  619. /**
  620. * Determine if something in the string is going to affect our ability to optimize. Checks for: '*' '.'
  621. */
  622. private boolean hasStarDot(String string, int pos) {
  623. for (int i = pos, max = string.length(); i < max; i++) {
  624. char ch = string.charAt(i);
  625. if (ch == '*' || ch == '.') {
  626. return true;
  627. }
  628. }
  629. return false;
  630. }
  631. /**
  632. * Checks if the type pattern looks like "com.foo..*"
  633. */
  634. private String looksLikeStartsWith(String typePattern) {
  635. if (hasSpaceAnnotationPlus(typePattern, 0) || typePattern.charAt(typePattern.length() - 1) != '*') {
  636. return null;
  637. }
  638. // now must looks like with "charsss..*" or "cha.rss..*" etc
  639. // note that "*" and "*..*" won't be fast matched
  640. // and that "charsss.*" will not neither
  641. int length = typePattern.length();
  642. if (typePattern.endsWith("..*") && length > 3) {
  643. if (typePattern.indexOf("..") == length - 3 // no ".." before last sequence
  644. && typePattern.indexOf('*') == length - 1) { // no earlier '*'
  645. return typePattern.substring(0, length - 2).replace('$', '.'); // "charsss." or "char.rss." etc
  646. }
  647. }
  648. return null;
  649. }
  650. /**
  651. * Register the dump filter
  652. *
  653. * @param weaver
  654. * @param loader
  655. * @param definitions
  656. */
  657. private void registerDump(final BcelWeaver weaver, final ClassLoader loader, final List<Definition> definitions) {
  658. for (Definition definition : definitions) {
  659. for (String dump : definition.getDumpPatterns()) {
  660. TypePattern pattern = new PatternParser(dump).parseTypePattern();
  661. dumpTypePattern.add(pattern);
  662. }
  663. if (definition.shouldDumpBefore()) {
  664. dumpBefore = true;
  665. }
  666. if (definition.createDumpDirPerClassloader()) {
  667. dumpDirPerClassloader = true;
  668. }
  669. }
  670. }
  671. /**
  672. * Determine whether a type should be accepted for weaving, by checking it against any includes/excludes.
  673. *
  674. * @param className the name of the type to possibly accept
  675. * @param bytes the bytecode for the type (in case we need to look inside, eg. annotations)
  676. * @return true if it should be accepted for weaving
  677. */
  678. @Override
  679. protected boolean accept(String className, byte[] bytes) {
  680. if (!hasExcludes && !hasIncludes) {
  681. return true;
  682. }
  683. // still try to avoid ResolvedType if we have simple patterns
  684. String fastClassName = className.replace('/', '.');
  685. for (String excludeStartsWithString : excludeStartsWith) {
  686. if (fastClassName.startsWith(excludeStartsWithString)) {
  687. return false;
  688. }
  689. }
  690. // Fast exclusion of patterns like: "*..*CGLIB*"
  691. if (!excludeStarDotDotStar.isEmpty()) {
  692. for (String namePiece : excludeStarDotDotStar) {
  693. int index = fastClassName.lastIndexOf('.');
  694. if (fastClassName.indexOf(namePiece, index + 1) != -1) {
  695. return false;
  696. }
  697. }
  698. }
  699. fastClassName = fastClassName.replace('$', '.');
  700. if (!excludeEndsWith.isEmpty()) {
  701. for (String lastPiece : excludeEndsWith) {
  702. if (fastClassName.endsWith(lastPiece)) {
  703. return false;
  704. }
  705. }
  706. }
  707. // Fast exclusion of exact names
  708. if (!excludeExactName.isEmpty()) {
  709. for (String name : excludeExactName) {
  710. if (fastClassName.equals(name)) {
  711. return false;
  712. }
  713. }
  714. }
  715. if (!excludeSpecial.isEmpty()) {
  716. for (String[] entry : excludeSpecial) {
  717. String excludeThese = entry[0];
  718. String exceptThese = entry[1];
  719. if (fastClassName.startsWith(excludeThese) && !fastClassName.startsWith(exceptThese)) {
  720. return false;
  721. }
  722. }
  723. }
  724. /*
  725. * Bug 120363 If we have an exclude pattern that cannot be matched using "starts with" then we cannot fast accept
  726. */
  727. boolean didSomeIncludeMatching = false;
  728. if (excludeTypePattern.isEmpty()) {
  729. if (includeStar) {
  730. return true;
  731. }
  732. if (!includeExactName.isEmpty()) {
  733. didSomeIncludeMatching = true;
  734. for (String exactname : includeExactName) {
  735. if (fastClassName.equals(exactname)) {
  736. return true;
  737. }
  738. }
  739. }
  740. boolean fastAccept = false;// defaults to false if no fast include
  741. for (String s : includeStartsWith) {
  742. didSomeIncludeMatching = true;
  743. fastAccept = fastClassName.startsWith(s);
  744. if (fastAccept) {
  745. return true;
  746. }
  747. }
  748. // We may have processed all patterns now... check that and return
  749. if (includeTypePattern.isEmpty()) {
  750. return !didSomeIncludeMatching;
  751. }
  752. }
  753. boolean accept;
  754. try {
  755. ensureDelegateInitialized(className, bytes);
  756. ResolvedType classInfo = delegateForCurrentClass.getResolvedTypeX();
  757. // exclude are "AND"ed
  758. for (TypePattern typePattern : excludeTypePattern) {
  759. if (typePattern.matchesStatically(classInfo)) {
  760. // exclude match - skip
  761. return false;
  762. }
  763. }
  764. // include are "OR"ed
  765. if (includeStar) {
  766. return true;
  767. }
  768. if (!includeExactName.isEmpty()) {
  769. didSomeIncludeMatching = true;
  770. for (String exactname : includeExactName) {
  771. if (fastClassName.equals(exactname)) {
  772. return true;
  773. }
  774. }
  775. }
  776. for (String s : includeStartsWith) {
  777. didSomeIncludeMatching = true;
  778. boolean fastaccept = fastClassName.startsWith(s);
  779. if (fastaccept) {
  780. return true;
  781. }
  782. }
  783. accept = !didSomeIncludeMatching; // only true if no includes at all
  784. for (TypePattern typePattern : includeTypePattern) {
  785. accept = typePattern.matchesStatically(classInfo);
  786. if (accept) {
  787. break;
  788. }
  789. // goes on if this include did not match ("OR"ed)
  790. }
  791. } finally {
  792. this.bcelWorld.demote();
  793. }
  794. return accept;
  795. }
  796. // FIXME we don't use include/exclude of others aop.xml
  797. // this can be nice but very dangerous as well to change that
  798. private boolean acceptAspect(String aspectClassName) {
  799. // avoid ResolvedType if not needed
  800. if (aspectExcludeTypePattern.isEmpty() && aspectIncludeTypePattern.isEmpty()) {
  801. return true;
  802. }
  803. // still try to avoid ResolvedType if we have simple patterns
  804. // EXCLUDE: if one match then reject
  805. String fastClassName = aspectClassName.replace('/', '.').replace('.', '$');
  806. for (String value : aspectExcludeStartsWith) {
  807. if (fastClassName.startsWith(value)) {
  808. return false;
  809. }
  810. }
  811. // INCLUDE: if one match then accept
  812. for (String s : aspectIncludeStartsWith) {
  813. if (fastClassName.startsWith(s)) {
  814. return true;
  815. }
  816. }
  817. // needs further analysis
  818. ResolvedType classInfo = weaver.getWorld().resolve(UnresolvedType.forName(aspectClassName), true);
  819. // exclude are "AND"ed
  820. for (TypePattern typePattern: aspectExcludeTypePattern) {
  821. if (typePattern.matchesStatically(classInfo)) {
  822. // exclude match - skip
  823. return false;
  824. }
  825. }
  826. // include are "OR"ed
  827. boolean accept = true;// defaults to true if no include
  828. for (TypePattern typePattern: aspectIncludeTypePattern) {
  829. accept = typePattern.matchesStatically(classInfo);
  830. if (accept) {
  831. break;
  832. }
  833. // goes on if this include did not match ("OR"ed)
  834. }
  835. return accept;
  836. }
  837. @Override
  838. protected boolean shouldDump(String className, boolean before) {
  839. // Don't dump before weaving unless asked to
  840. if (before && !dumpBefore) {
  841. return false;
  842. }
  843. // avoid ResolvedType if not needed
  844. if (dumpTypePattern.isEmpty()) {
  845. return false;
  846. }
  847. // TODO AV - optimize for className.startWith only
  848. ResolvedType classInfo = weaver.getWorld().resolve(UnresolvedType.forName(className), true);
  849. // dump
  850. for (TypePattern typePattern : dumpTypePattern) {
  851. if (typePattern.matchesStatically(classInfo)) {
  852. // dump match
  853. return true;
  854. }
  855. }
  856. return false;
  857. }
  858. @Override
  859. protected String getDumpDir() {
  860. if (dumpDirPerClassloader) {
  861. StringBuilder dir = new StringBuilder();
  862. dir.append("_ajdump").append(File.separator).append(weavingContext.getId());
  863. return dir.toString();
  864. } else {
  865. return super.getDumpDir();
  866. }
  867. }
  868. /*
  869. * shared classes methods
  870. */
  871. /**
  872. * @return Returns the key.
  873. */
  874. public String getNamespace() {
  875. // System.out.println("ClassLoaderWeavingAdaptor.getNamespace() classloader=" + weavingContext.getClassLoaderName() +
  876. // ", namespace=" + namespace);
  877. if (namespace == null) {
  878. return "";
  879. } else {
  880. return new String(namespace);
  881. }
  882. }
  883. /**
  884. * Check to see if any classes are stored in the generated classes cache. Then flush the cache if it is not empty
  885. *
  886. * @param className TODO
  887. * @return true if a class has been generated and is stored in the cache
  888. */
  889. public boolean generatedClassesExistFor(String className) {
  890. // System.err.println("? ClassLoaderWeavingAdaptor.generatedClassesExist() classname=" + className + ", size=" +
  891. // generatedClasses);
  892. if (className == null) {
  893. return !generatedClasses.isEmpty();
  894. } else {
  895. return generatedClasses.containsKey(className);
  896. }
  897. }
  898. /**
  899. * Flush the generated classes cache
  900. */
  901. public void flushGeneratedClasses() {
  902. // System.err.println("? ClassLoaderWeavingAdaptor.flushGeneratedClasses() generatedClasses=" + generatedClasses);
  903. generatedClasses = new HashMap<>();
  904. }
  905. /**
  906. * Remove generated classes based on the supplied className. This will
  907. * remove any entries related to this name - so the class itself plus
  908. * and inner classes.
  909. * @param className a slashed classname (e.g. com/foo/Bar)
  910. */
  911. public void flushGeneratedClassesFor(String className) {
  912. try {
  913. String dottedClassName = className.replace('/', '.');
  914. String dottedClassNameDollar = dottedClassName+"$"; // to pickup inner classes
  915. Iterator<Map.Entry<String, IUnwovenClassFile>> iter = generatedClasses.entrySet().iterator();
  916. while (iter.hasNext()) {
  917. Entry<String, IUnwovenClassFile> next = iter.next();
  918. String existingGeneratedName = next.getKey();
  919. if (existingGeneratedName.equals(dottedClassName) ||
  920. existingGeneratedName.startsWith(dottedClassNameDollar)) {
  921. iter.remove();
  922. }
  923. }
  924. } catch (Throwable t) {
  925. new RuntimeException("Unexpected problem tidying up generated classes for "+className,t).printStackTrace();
  926. }
  927. }
  928. private Unsafe unsafe;
  929. private Unsafe getUnsafe() throws NoSuchFieldException, IllegalAccessException {
  930. if (unsafe == null) {
  931. Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
  932. theUnsafeField.setAccessible(true);
  933. return (Unsafe) theUnsafeField.get(null);
  934. }
  935. return unsafe;
  936. }
  937. private static Method bindTo_Method, invokeWithArguments_Method = null;
  938. private static Object defineClassMethodHandle = null;
  939. private static Boolean initializedForJava11 = false;
  940. // In order to let this code compile on earlier versions of Java (8), use reflection to discover the elements
  941. // we need to define classes.
  942. private static synchronized void initializeForJava11() {
  943. if (initializedForJava11) return;
  944. try {
  945. // MethodType defineClassMethodType = MethodType.methodType(Class.class, new Class[]{String.class, byte[].class, int.class, int.class, ProtectionDomain.class});
  946. Class<?> methodType_Class = Class.forName("java.lang.invoke.MethodType");
  947. Method methodTypeMethodOnMethodTypeClass = methodType_Class.getDeclaredMethod("methodType", Class.class,Class[].class);
  948. methodTypeMethodOnMethodTypeClass.setAccessible(true);
  949. Object defineClassMethodType = methodTypeMethodOnMethodTypeClass.invoke(null, Class.class, new Class[] {String.class,byte[].class,int.class,int.class,ProtectionDomain.class});
  950. // MethodHandles.Lookup methodHandlesLookup = MethodHandles.lookup();
  951. Class<?> methodHandles_Class = Class.forName("java.lang.invoke.MethodHandles");
  952. Method lookupMethodOnMethodHandlesClass = methodHandles_Class.getDeclaredMethod("lookup");
  953. lookupMethodOnMethodHandlesClass.setAccessible(true);
  954. Object methodHandlesLookup = lookupMethodOnMethodHandlesClass.invoke(null);
  955. // MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(ClassLoader.class, methodHandlesLookup);
  956. Class<?> methodHandlesLookup_Class = Class.forName("java.lang.invoke.MethodHandles$Lookup");
  957. Method privateLookupMethodOnMethodHandlesClass = methodHandles_Class.getDeclaredMethod("privateLookupIn",Class.class,methodHandlesLookup_Class);
  958. privateLookupMethodOnMethodHandlesClass.setAccessible(true);
  959. Object lookup = privateLookupMethodOnMethodHandlesClass.invoke(null, ClassLoader.class, methodHandlesLookup);
  960. // MethodHandle defineClassMethodHandle = lookup.findVirtual(ClassLoader.class, "defineClass", defineClassMethodType);
  961. Method findVirtual_Method = methodHandlesLookup_Class.getDeclaredMethod("findVirtual", Class.class,String.class,methodType_Class);
  962. findVirtual_Method.setAccessible(true);
  963. defineClassMethodHandle = findVirtual_Method.invoke(lookup, ClassLoader.class, "defineClass",defineClassMethodType);
  964. // clazz = defineClassMethodHandle.bindTo(loader).invokeWithArguments(name, bytes, 0, bytes.length);
  965. Class<?> methodHandle_Class = Class.forName("java.lang.invoke.MethodHandle");
  966. bindTo_Method = methodHandle_Class.getDeclaredMethod("bindTo", Object.class);
  967. invokeWithArguments_Method = methodHandle_Class.getDeclaredMethod("invokeWithArguments",Object[].class);
  968. initializedForJava11 = true;
  969. } catch (Exception e) {
  970. e.printStackTrace();
  971. }
  972. }
  973. private void defineClass(ClassLoader loader, String name, byte[] bytes, ProtectionDomain protectionDomain) {
  974. if (trace.isTraceEnabled()) {
  975. trace.enter("defineClass", this, new Object[] { loader, name, bytes });
  976. }
  977. Object clazz = null;
  978. debug("generating class '" + name + "'");
  979. if (LangUtil.is11VMOrGreater()) {
  980. try {
  981. if (!initializedForJava11) {
  982. initializeForJava11();
  983. }
  984. // Do this: clazz = defineClassMethodHandle.bindTo(loader).invokeWithArguments(name, bytes, 0, bytes.length, protectionDomain);
  985. Object o = bindTo_Method.invoke(defineClassMethodHandle,loader);
  986. clazz = invokeWithArguments_Method.invoke(o, new Object[] {new Object[] {name, bytes, 0, bytes.length, protectionDomain}});
  987. } catch (Throwable t) {
  988. t.printStackTrace(System.err);
  989. warn("define generated class failed", t);
  990. }
  991. } else {
  992. try {
  993. if (defineClassMethod == null) {
  994. synchronized (lock) {
  995. getUnsafe();
  996. defineClassMethod =
  997. Unsafe.class.getDeclaredMethod("defineClass", String.class,byte[].class,Integer.TYPE,Integer.TYPE, ClassLoader.class,ProtectionDomain.class);
  998. }
  999. }
  1000. defineClassMethod.setAccessible(true);
  1001. clazz = defineClassMethod.invoke(getUnsafe(), name,bytes,0,bytes.length,loader,protectionDomain);
  1002. } catch (LinkageError le) {
  1003. le.printStackTrace();
  1004. // likely thrown due to defining something that already exists?
  1005. // Old comments from before moving to Unsafe.defineClass():
  1006. // is already defined (happens for X$ajcMightHaveAspect interfaces since aspects are reweaved)
  1007. // TODO maw I don't think this is OK and
  1008. } catch (Exception e) {
  1009. e.printStackTrace(System.err);
  1010. warn("define generated class failed", e);
  1011. }
  1012. }
  1013. if (trace.isTraceEnabled()) {
  1014. trace.exit("defineClass", clazz);
  1015. }
  1016. }
  1017. static Method defineClassMethod;
  1018. private static final Object lock = new Object();
  1019. // /*
  1020. // This method is equivalent to the following code but use reflection to compile on Java 7:
  1021. // MethodHandles.Lookup baseLookup = MethodHandles.lookup();
  1022. // MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(ClassLoader.class, baseLookup);
  1023. // MethodHandle defineClassMethodHandle = lookup.findVirtual(ClassLoader.class, "defineClass", defineClassMethodType);
  1024. // handle.bindTo(classLoader).invokeWithArguments(className, classBytes, 0, classBytes.length));
  1025. // */
  1026. //@Override
  1027. //@SuppressWarnings("unchecked")
  1028. //public <T> Class<T> defineClass(ClassLoader classLoader, String className, byte[] classBytes) {
  1029. // Object baseLookup = methodHandlesLookup.invoke(null);
  1030. // Object lookup = methodHandlesPrivateLookupIn.invoke(null, ClassLoader.class, baseLookup);
  1031. // MethodHandle defineClassMethodHandle = (MethodHandle) lookupFindVirtual.invoke(lookup, ClassLoader.class, "defineClass", defineClassMethodType);
  1032. // try {
  1033. // return Cast.uncheckedCast(defineClassMethodHandle.bindTo(classLoader).invokeWithArguments(className, classBytes, 0, classBytes.length));
  1034. // } catch (Throwable throwable) {
  1035. // throw new RuntimeException(throwable);
  1036. // return (Class) defineClassMethodHandle.bindTo(classLoader).invokeWithArguments(className, classBytes, 0, classBytes.length);
  1037. // } catch (Throwable e) {
  1038. // throw new RuntimeException(e);
  1039. // }
  1040. //}
  1041. private void defineClass(ClassLoader loader, String name, byte[] bytes){
  1042. defineClass(loader,name,bytes,null);//, ProtectionDomain protectionDomain) {
  1043. }
  1044. // if (trace.isTraceEnabled()) {
  1045. // trace.enter("defineClass", this, new Object[] { loader, name, bytes, protectionDomain });
  1046. // }
  1047. // Object clazz = null;
  1048. // debug("generating class '" + name + "'");
  1049. // try {
  1050. // getUnsafe().defineClass(name, bytes, 0, bytes.length, loader, protectionDomain);
  1051. // } catch (LinkageError le) {
  1052. // // likely thrown due to defining something that already exists?
  1053. // // Old comments from before moving to Unsafe.defineClass():
  1054. // // is already defined (happens for X$ajcMightHaveAspect interfaces since aspects are reweaved)
  1055. // // TODO maw I don't think this is OK and
  1056. // } catch (Exception e) {
  1057. // warn("define generated class failed", e);
  1058. // }
  1059. //
  1060. // if (trace.isTraceEnabled()) {
  1061. // trace.exit("defineClass", clazz);
  1062. // }
  1063. // }
  1064. }