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.

преди 19 години
преди 13 години
преди 19 години
преди 19 години
преди 11 години
преди 19 години
преди 16 години
преди 19 години
преди 11 години
преди 16 години
преди 16 години
преди 11 години
преди 16 години
преди 16 години
преди 16 години
преди 13 години
преди 16 години
преди 16 години
преди 11 години
преди 16 години
преди 13 години
преди 13 години
преди 13 години
преди 11 години
преди 13 години
преди 16 години
преди 11 години
преди 16 години
преди 11 години
преди 16 години
преди 16 години
преди 11 години
преди 16 години
преди 11 години
преди 16 години
преди 11 години
преди 16 години
преди 16 години
преди 11 години
преди 16 години
преди 9 години
преди 16 години
преди 9 години
преди 16 години
преди 16 години
преди 16 години
преди 9 години
преди 16 години
преди 16 години
преди 10 години
преди 11 години
преди 16 години
преди 10 години
преди 11 години
преди 10 години
преди 16 години
преди 11 години
преди 16 години
преди 11 години
преди 10 години
преди 11 години
преди 16 години
преди 16 години
преди 19 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. /*******************************************************************************
  2. * Copyright (c) 2005 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. * Contributors:
  10. * Alexandre Vasseur initial implementation
  11. *******************************************************************************/
  12. package org.aspectj.weaver.loadtime;
  13. import java.lang.ref.ReferenceQueue;
  14. import java.lang.ref.WeakReference;
  15. import java.security.ProtectionDomain;
  16. import java.util.ArrayList;
  17. import java.util.Collections;
  18. import java.util.HashMap;
  19. import java.util.Iterator;
  20. import java.util.List;
  21. import java.util.Map;
  22. import java.util.Set;
  23. import java.util.StringTokenizer;
  24. import org.aspectj.bridge.context.CompilationAndWeavingContext;
  25. import org.aspectj.weaver.Dump;
  26. import org.aspectj.weaver.tools.Trace;
  27. import org.aspectj.weaver.tools.TraceFactory;
  28. import org.aspectj.weaver.tools.WeavingAdaptor;
  29. import org.aspectj.weaver.tools.cache.SimpleCache;
  30. import org.aspectj.weaver.tools.cache.SimpleCacheFactory;
  31. /**
  32. * Adapter between the generic class pre processor interface and the AspectJ weaver Load time weaving consistency relies on
  33. * Bcel.setRepository
  34. *
  35. * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
  36. */
  37. public class Aj implements ClassPreProcessor {
  38. private IWeavingContext weavingContext;
  39. public static SimpleCache laCache=SimpleCacheFactory.createSimpleCache();
  40. /**
  41. * References are added to this queue when their associated classloader is removed, and once on here that indicates that we
  42. * should tidy up the adaptor map and remove the adaptor (weaver) from the map we are maintaining from adaptorkey > adaptor
  43. * (weaver)
  44. */
  45. private static ReferenceQueue adaptorQueue = new ReferenceQueue();
  46. private static Trace trace = TraceFactory.getTraceFactory().getTrace(Aj.class);
  47. public Aj() {
  48. this(null);
  49. }
  50. public Aj(IWeavingContext context) {
  51. if (trace.isTraceEnabled())
  52. trace.enter("<init>", this, new Object[] { context, getClass().getClassLoader() });
  53. this.weavingContext = context;
  54. if (trace.isTraceEnabled())
  55. trace.exit("<init>");
  56. }
  57. /**
  58. * Initialization
  59. */
  60. @Override
  61. public void initialize() {
  62. }
  63. private final static String deleLoader = "sun.reflect.DelegatingClassLoader";
  64. private final static String deleLoader2 = "jdk.internal.reflect.DelegatingClassLoader"; // On JDK11+
  65. @Override
  66. public byte[] preProcess(String className, byte[] bytes, ClassLoader loader, ProtectionDomain protectionDomain) {
  67. if (loader == null || className == null ||
  68. loader.getClass().getName().equals(deleLoader) || loader.getClass().getName().equals(deleLoader2)) {
  69. // skip boot loader, null classes (hibernate), or those from a reflection loader
  70. return bytes;
  71. }
  72. if (loadersToSkip != null) {
  73. // Check whether to reject it
  74. if (loadersToSkip.contains(loader.getClass().getName())) {
  75. // System.out.println("debug: no weaver created for loader '"+loader.getClass().getName()+"'");
  76. return bytes;
  77. }
  78. }
  79. if (trace.isTraceEnabled())
  80. trace.enter("preProcess", this, new Object[] { className, bytes, loader });
  81. if (trace.isTraceEnabled())
  82. trace.event("preProcess", this, new Object[] { loader.getParent(), Thread.currentThread().getContextClassLoader() });
  83. try {
  84. synchronized (loader) {
  85. if (SimpleCacheFactory.isEnabled()) {
  86. byte[] cacheBytes= laCache.getAndInitialize(className, bytes,loader,protectionDomain);
  87. if (cacheBytes!=null){
  88. return cacheBytes;
  89. }
  90. }
  91. WeavingAdaptor weavingAdaptor = WeaverContainer.getWeaver(loader, weavingContext);
  92. if (weavingAdaptor == null) {
  93. if (trace.isTraceEnabled())
  94. trace.exit("preProcess");
  95. return bytes;
  96. }
  97. try {
  98. weavingAdaptor.setActiveProtectionDomain(protectionDomain);
  99. byte[] newBytes = weavingAdaptor.weaveClass(className, bytes, false);
  100. Dump.dumpOnExit(weavingAdaptor.getMessageHolder(), true);
  101. if (trace.isTraceEnabled())
  102. trace.exit("preProcess", newBytes);
  103. if (SimpleCacheFactory.isEnabled()) {
  104. laCache.put(className, bytes, newBytes);
  105. }
  106. return newBytes;
  107. } finally {
  108. weavingAdaptor.setActiveProtectionDomain(null);
  109. }
  110. }
  111. /* Don't like to do this but JVMTI swallows all exceptions */
  112. } catch (Throwable th) {
  113. trace.error(className, th);
  114. Dump.dumpWithException(th);
  115. // FIXME AV wondering if we should have the option to fail (throw runtime exception) here
  116. // would make sense at least in test f.e. see TestHelper.handleMessage()
  117. if (trace.isTraceEnabled())
  118. trace.exit("preProcess", th);
  119. return bytes;
  120. } finally {
  121. CompilationAndWeavingContext.resetForThread();
  122. }
  123. }
  124. /**
  125. * An AdaptorKey is a WeakReference wrapping a classloader reference that will enqueue to a specified queue when the classloader
  126. * is GC'd. Since the AdaptorKey is used as a key into a hashmap we need to give it a non-varying hashcode/equals
  127. * implementation, and we need that hashcode not to vary even when the internal referent has been GC'd. The hashcode is
  128. * calculated on creation of the AdaptorKey based on the loader instance that it is wrapping. This means even when the referent
  129. * is gone we can still use the AdaptorKey and it will 'point' to the same place as it always did.
  130. */
  131. private static class AdaptorKey extends WeakReference {
  132. private final int loaderHashCode, sysHashCode, hashValue;
  133. private final String loaderClass;
  134. public AdaptorKey(ClassLoader loader) {
  135. super(loader, adaptorQueue);
  136. loaderHashCode = loader.hashCode();
  137. sysHashCode = System.identityHashCode(loader);
  138. loaderClass = loader.getClass().getName();
  139. hashValue = loaderHashCode + sysHashCode + loaderClass.hashCode();
  140. }
  141. public ClassLoader getClassLoader() {
  142. ClassLoader instance = (ClassLoader) get();
  143. // Assert instance!=null - shouldn't be asked for after a GC of the referent has occurred !
  144. return instance;
  145. }
  146. @Override
  147. public boolean equals(Object obj) {
  148. if (!(obj instanceof AdaptorKey)) {
  149. return false;
  150. }
  151. AdaptorKey other = (AdaptorKey) obj;
  152. return (other.loaderHashCode == loaderHashCode)
  153. && (other.sysHashCode == sysHashCode)
  154. && loaderClass.equals(other.loaderClass);
  155. }
  156. @Override
  157. public int hashCode() {
  158. return hashValue;
  159. }
  160. }
  161. /**
  162. * The reference queue is only processed when a request is made for a weaver adaptor. This means there can be one or two stale
  163. * weavers left around. If the user knows they have finished all their weaving, they might wish to call removeStaleAdaptors
  164. * which will process anything left on the reference queue containing adaptorKeys for garbage collected classloaders.
  165. *
  166. * @param displayProgress produce System.err info on the tidying up process
  167. * @return number of stale weavers removed
  168. */
  169. public static int removeStaleAdaptors(boolean displayProgress) {
  170. int removed = 0;
  171. synchronized (WeaverContainer.weavingAdaptors) {
  172. if (displayProgress) {
  173. System.err.println("Weaver adaptors before queue processing:");
  174. Map<AdaptorKey,ExplicitlyInitializedClassLoaderWeavingAdaptor> m = WeaverContainer.weavingAdaptors;
  175. Set<AdaptorKey> keys = m.keySet();
  176. for (Object object : keys) {
  177. System.err.println(object + " = " + WeaverContainer.weavingAdaptors.get(object));
  178. }
  179. }
  180. Object o = adaptorQueue.poll();
  181. while (o != null) {
  182. if (displayProgress)
  183. System.err.println("Processing referencequeue entry " + o);
  184. AdaptorKey wo = (AdaptorKey) o;
  185. boolean didit = WeaverContainer.weavingAdaptors.remove(wo) != null;
  186. if (didit) {
  187. removed++;
  188. } else {
  189. throw new RuntimeException("Eh?? key=" + wo);
  190. }
  191. if (displayProgress)
  192. System.err.println("Removed? " + didit);
  193. o = adaptorQueue.poll();
  194. }
  195. if (displayProgress) {
  196. System.err.println("Weaver adaptors after queue processing:");
  197. Map<AdaptorKey,ExplicitlyInitializedClassLoaderWeavingAdaptor> m = WeaverContainer.weavingAdaptors;
  198. Set<AdaptorKey> keys = m.keySet();
  199. for (Object object : keys) {
  200. System.err.println(object + " = " + WeaverContainer.weavingAdaptors.get(object));
  201. }
  202. }
  203. }
  204. return removed;
  205. }
  206. /**
  207. * @return the number of entries still in the weavingAdaptors map
  208. */
  209. public static int getActiveAdaptorCount() {
  210. return WeaverContainer.weavingAdaptors.size();
  211. }
  212. /**
  213. * Process the reference queue that contains stale AdaptorKeys - the keys are put on the queue when their classloader referent
  214. * is garbage collected and so the associated adaptor (weaver) should be removed from the map
  215. */
  216. public static void checkQ() {
  217. synchronized (adaptorQueue) {
  218. Object o = adaptorQueue.poll();
  219. while (o != null) {
  220. AdaptorKey wo = (AdaptorKey) o;
  221. // boolean removed =
  222. WeaverContainer.weavingAdaptors.remove(wo);
  223. // DBG System.err.println("Evicting key " + wo + " = " + didit);
  224. o = adaptorQueue.poll();
  225. }
  226. }
  227. }
  228. public static List<String> loadersToSkip = null;
  229. static {
  230. // pr271840 - touch the types early and outside the locks
  231. new ExplicitlyInitializedClassLoaderWeavingAdaptor(new ClassLoaderWeavingAdaptor());
  232. try {
  233. String loadersToSkipProperty = System.getProperty("aj.weaving.loadersToSkip","");
  234. StringTokenizer st = new StringTokenizer(loadersToSkipProperty, ",");
  235. if (loadersToSkipProperty != null && loadersToSkip == null) {
  236. if (st.hasMoreTokens()) {
  237. // System.out.println("aj.weaving.loadersToSkip is set. Skipping loaders: '"+loadersToSkipProperty+"'");
  238. loadersToSkip = new ArrayList<String>();
  239. }
  240. while (st.hasMoreTokens()) {
  241. String nextLoader = st.nextToken();
  242. loadersToSkip.add(nextLoader);
  243. }
  244. }
  245. } catch (Exception e) {
  246. // Likely security issue related to property access...
  247. }
  248. }
  249. /**
  250. * Cache of weaver There is one weaver per classloader
  251. */
  252. static class WeaverContainer {
  253. final static Map<AdaptorKey,ExplicitlyInitializedClassLoaderWeavingAdaptor> weavingAdaptors =
  254. Collections.synchronizedMap(new HashMap<AdaptorKey,ExplicitlyInitializedClassLoaderWeavingAdaptor>());
  255. static WeavingAdaptor getWeaver(ClassLoader loader, IWeavingContext weavingContext) {
  256. ExplicitlyInitializedClassLoaderWeavingAdaptor adaptor = null;
  257. AdaptorKey adaptorKey = new AdaptorKey(loader);
  258. String loaderClassName = loader.getClass().getName();
  259. synchronized (weavingAdaptors) {
  260. checkQ();
  261. if (loader.equals(myClassLoader)){
  262. adaptor = myClassLoaderAdaptor;
  263. } else {
  264. adaptor = weavingAdaptors.get(adaptorKey);
  265. }
  266. if (adaptor == null) {
  267. // create it and put it back in the weavingAdaptors map but avoid any kind of instantiation
  268. // within the synchronized block
  269. ClassLoaderWeavingAdaptor weavingAdaptor = new ClassLoaderWeavingAdaptor();
  270. adaptor = new ExplicitlyInitializedClassLoaderWeavingAdaptor(weavingAdaptor);
  271. if(myClassLoaderAdaptor == null && loader.equals(myClassLoader)){
  272. myClassLoaderAdaptor = adaptor;
  273. } else {
  274. weavingAdaptors.put(adaptorKey, adaptor);
  275. }
  276. }
  277. }
  278. // perform the initialization
  279. return adaptor.getWeavingAdaptor(loader, weavingContext);
  280. }
  281. private static final ClassLoader myClassLoader = WeavingAdaptor.class.getClassLoader();
  282. private static ExplicitlyInitializedClassLoaderWeavingAdaptor myClassLoaderAdaptor;
  283. }
  284. static class ExplicitlyInitializedClassLoaderWeavingAdaptor {
  285. private final ClassLoaderWeavingAdaptor weavingAdaptor;
  286. private boolean isInitialized;
  287. public ExplicitlyInitializedClassLoaderWeavingAdaptor(ClassLoaderWeavingAdaptor weavingAdaptor) {
  288. this.weavingAdaptor = weavingAdaptor;
  289. this.isInitialized = false;
  290. }
  291. private void initialize(ClassLoader loader, IWeavingContext weavingContext) {
  292. if (!isInitialized) {
  293. isInitialized = true;
  294. weavingAdaptor.initialize(loader, weavingContext);
  295. }
  296. }
  297. public ClassLoaderWeavingAdaptor getWeavingAdaptor(ClassLoader loader, IWeavingContext weavingContext) {
  298. initialize(loader, weavingContext);
  299. return weavingAdaptor;
  300. }
  301. }
  302. /**
  303. * Returns a namespace based on the contest of the aspects available
  304. */
  305. public String getNamespace(ClassLoader loader) {
  306. ClassLoaderWeavingAdaptor weavingAdaptor = (ClassLoaderWeavingAdaptor) WeaverContainer.getWeaver(loader, weavingContext);
  307. return weavingAdaptor.getNamespace();
  308. }
  309. /**
  310. * Check to see if any classes have been generated for a particular classes loader. Calls
  311. * ClassLoaderWeavingAdaptor.generatedClassesExist()
  312. *
  313. * @param loader the class cloder
  314. * @return true if classes have been generated.
  315. */
  316. public boolean generatedClassesExist(ClassLoader loader) {
  317. return ((ClassLoaderWeavingAdaptor) WeaverContainer.getWeaver(loader, weavingContext)).generatedClassesExistFor(null);
  318. }
  319. public void flushGeneratedClasses(ClassLoader loader) {
  320. ((ClassLoaderWeavingAdaptor) WeaverContainer.getWeaver(loader, weavingContext)).flushGeneratedClasses();
  321. }
  322. @Override
  323. public void prepareForRedefinition(ClassLoader loader, String className) {
  324. ((ClassLoaderWeavingAdaptor) WeaverContainer.getWeaver(loader, weavingContext)).flushGeneratedClassesFor(className);
  325. }
  326. }