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.

ClassLoaderWeavingAdaptor.java 41KB

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