Skip to content

Commit b82df14

Browse files
committed
LoadTimeWeaver.getThrowawayClassLoader() decorated for exclude support (if necessary)
Issue: SPR-13886
1 parent 448621a commit b82df14

File tree

8 files changed

+97
-62
lines changed

8 files changed

+97
-62
lines changed

spring-context/src/main/java/org/springframework/instrument/classloading/ReflectiveLoadTimeWeaver.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,6 +22,8 @@
2222
import org.apache.commons.logging.Log;
2323
import org.apache.commons.logging.LogFactory;
2424

25+
import org.springframework.core.DecoratingClassLoader;
26+
import org.springframework.core.OverridingClassLoader;
2527
import org.springframework.util.Assert;
2628
import org.springframework.util.ClassUtils;
2729
import org.springframework.util.ReflectionUtils;
@@ -97,15 +99,14 @@ public ReflectiveLoadTimeWeaver(ClassLoader classLoader) {
9799
Assert.notNull(classLoader, "ClassLoader must not be null");
98100
this.classLoader = classLoader;
99101
this.addTransformerMethod = ClassUtils.getMethodIfAvailable(
100-
this.classLoader.getClass(), ADD_TRANSFORMER_METHOD_NAME,
101-
new Class<?>[] {ClassFileTransformer.class});
102+
this.classLoader.getClass(), ADD_TRANSFORMER_METHOD_NAME, ClassFileTransformer.class);
102103
if (this.addTransformerMethod == null) {
103104
throw new IllegalStateException(
104105
"ClassLoader [" + classLoader.getClass().getName() + "] does NOT provide an " +
105106
"'addTransformer(ClassFileTransformer)' method.");
106107
}
107108
this.getThrowawayClassLoaderMethod = ClassUtils.getMethodIfAvailable(
108-
this.classLoader.getClass(), GET_THROWAWAY_CLASS_LOADER_METHOD_NAME, new Class<?>[0]);
109+
this.classLoader.getClass(), GET_THROWAWAY_CLASS_LOADER_METHOD_NAME);
109110
// getThrowawayClassLoader method is optional
110111
if (this.getThrowawayClassLoaderMethod == null) {
111112
if (logger.isInfoEnabled()) {
@@ -130,7 +131,10 @@ public ClassLoader getInstrumentableClassLoader() {
130131
@Override
131132
public ClassLoader getThrowawayClassLoader() {
132133
if (this.getThrowawayClassLoaderMethod != null) {
133-
return (ClassLoader) ReflectionUtils.invokeMethod(this.getThrowawayClassLoaderMethod, this.classLoader);
134+
ClassLoader target = (ClassLoader)
135+
ReflectionUtils.invokeMethod(this.getThrowawayClassLoaderMethod, this.classLoader);
136+
return (target instanceof DecoratingClassLoader ? target :
137+
new OverridingClassLoader(this.classLoader, target));
134138
}
135139
else {
136140
return new SimpleThrowawayClassLoader(this.classLoader);

spring-context/src/main/java/org/springframework/instrument/classloading/glassfish/GlassFishLoadTimeWeaver.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
2020
import java.lang.reflect.InvocationTargetException;
2121
import java.lang.reflect.Method;
2222

23+
import org.springframework.core.OverridingClassLoader;
2324
import org.springframework.instrument.classloading.LoadTimeWeaver;
2425
import org.springframework.util.Assert;
2526
import org.springframework.util.ClassUtils;
@@ -109,7 +110,7 @@ public ClassLoader getInstrumentableClassLoader() {
109110
@Override
110111
public ClassLoader getThrowawayClassLoader() {
111112
try {
112-
return (ClassLoader) this.copyMethod.invoke(this.classLoader);
113+
return new OverridingClassLoader(this.classLoader, (ClassLoader) this.copyMethod.invoke(this.classLoader));
113114
}
114115
catch (InvocationTargetException ex) {
115116
throw new IllegalStateException("GlassFish copy method threw exception", ex.getCause());

spring-context/src/main/java/org/springframework/instrument/classloading/tomcat/TomcatLoadTimeWeaver.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
2020
import java.lang.reflect.InvocationTargetException;
2121
import java.lang.reflect.Method;
2222

23+
import org.springframework.core.OverridingClassLoader;
2324
import org.springframework.instrument.classloading.LoadTimeWeaver;
2425
import org.springframework.util.Assert;
2526
import org.springframework.util.ClassUtils;
@@ -103,7 +104,7 @@ public ClassLoader getInstrumentableClassLoader() {
103104
@Override
104105
public ClassLoader getThrowawayClassLoader() {
105106
try {
106-
return (ClassLoader) this.copyMethod.invoke(this.classLoader);
107+
return new OverridingClassLoader(this.classLoader, (ClassLoader) this.copyMethod.invoke(this.classLoader));
107108
}
108109
catch (InvocationTargetException ex) {
109110
throw new IllegalStateException("Tomcat copy method threw exception", ex.getCause());

spring-context/src/main/java/org/springframework/instrument/classloading/weblogic/WebLogicLoadTimeWeaver.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818

1919
import java.lang.instrument.ClassFileTransformer;
2020

21+
import org.springframework.core.OverridingClassLoader;
2122
import org.springframework.instrument.classloading.LoadTimeWeaver;
2223
import org.springframework.util.Assert;
2324
import org.springframework.util.ClassUtils;
@@ -70,6 +71,8 @@ public ClassLoader getInstrumentableClassLoader() {
7071

7172
@Override
7273
public ClassLoader getThrowawayClassLoader() {
73-
return this.classLoader.getThrowawayClassLoader();
74+
return new OverridingClassLoader(this.classLoader.getClassLoader(),
75+
this.classLoader.getThrowawayClassLoader());
7476
}
77+
7578
}

spring-context/src/main/java/org/springframework/instrument/classloading/websphere/WebSphereClassLoaderAdapter.java

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -29,47 +29,57 @@
2929

3030
/**
3131
*
32-
* Reflective wrapper around a WebSphere 7 class loader. Used to
32+
* Reflective wrapper around a WebSphere 7+ class loader. Used to
3333
* encapsulate the classloader-specific methods (discovered and
3434
* called through reflection) from the load-time weaver.
3535
*
3636
* @author Costin Leau
37+
* @author Juergen Hoeller
3738
* @since 3.1
3839
*/
3940
class WebSphereClassLoaderAdapter {
4041

4142
private static final String COMPOUND_CLASS_LOADER_NAME = "com.ibm.ws.classloader.CompoundClassLoader";
43+
4244
private static final String CLASS_PRE_PROCESSOR_NAME = "com.ibm.websphere.classloader.ClassLoaderInstancePreDefinePlugin";
45+
4346
private static final String PLUGINS_FIELD = "preDefinePlugins";
4447

4548
private ClassLoader classLoader;
49+
4650
private Class<?> wsPreProcessorClass;
51+
4752
private Method addPreDefinePlugin;
53+
4854
private Constructor<? extends ClassLoader> cloneConstructor;
55+
4956
private Field transformerList;
5057

58+
5159
public WebSphereClassLoaderAdapter(ClassLoader classLoader) {
52-
Class<?> wsCompoundClassLoaderClass = null;
60+
Class<?> wsCompoundClassLoaderClass;
5361
try {
5462
wsCompoundClassLoaderClass = classLoader.loadClass(COMPOUND_CLASS_LOADER_NAME);
55-
cloneConstructor = classLoader.getClass().getDeclaredConstructor(wsCompoundClassLoaderClass);
56-
cloneConstructor.setAccessible(true);
63+
this.cloneConstructor = classLoader.getClass().getDeclaredConstructor(wsCompoundClassLoaderClass);
64+
this.cloneConstructor.setAccessible(true);
5765

58-
wsPreProcessorClass = classLoader.loadClass(CLASS_PRE_PROCESSOR_NAME);
59-
addPreDefinePlugin = classLoader.getClass().getMethod("addPreDefinePlugin", wsPreProcessorClass);
60-
transformerList = wsCompoundClassLoaderClass.getDeclaredField(PLUGINS_FIELD);
61-
transformerList.setAccessible(true);
66+
this.wsPreProcessorClass = classLoader.loadClass(CLASS_PRE_PROCESSOR_NAME);
67+
this.addPreDefinePlugin = classLoader.getClass().getMethod("addPreDefinePlugin", this.wsPreProcessorClass);
68+
this.transformerList = wsCompoundClassLoaderClass.getDeclaredField(PLUGINS_FIELD);
69+
this.transformerList.setAccessible(true);
6270
}
6371
catch (Exception ex) {
6472
throw new IllegalStateException(
65-
"Could not initialize WebSphere LoadTimeWeaver because WebSphere 7 API classes are not available",
66-
ex);
73+
"Could not initialize WebSphere LoadTimeWeaver because WebSphere API classes are not available", ex);
74+
}
75+
76+
if (!wsCompoundClassLoaderClass.isInstance(classLoader)) {
77+
throw new IllegalArgumentException("ClassLoader must be instance of [" + COMPOUND_CLASS_LOADER_NAME + "]");
6778
}
68-
Assert.isInstanceOf(wsCompoundClassLoaderClass, classLoader,
69-
"ClassLoader must be instance of [" + COMPOUND_CLASS_LOADER_NAME + "]");
7079
this.classLoader = classLoader;
7180
}
7281

82+
7383
public ClassLoader getClassLoader() {
7484
return this.classLoader;
7585
}
@@ -79,9 +89,8 @@ public void addTransformer(ClassFileTransformer transformer) {
7989
try {
8090
InvocationHandler adapter = new WebSphereClassPreDefinePlugin(transformer);
8191
Object adapterInstance = Proxy.newProxyInstance(this.wsPreProcessorClass.getClassLoader(),
82-
new Class<?>[] { this.wsPreProcessorClass }, adapter);
92+
new Class<?>[] {this.wsPreProcessorClass}, adapter);
8393
this.addPreDefinePlugin.invoke(this.classLoader, adapterInstance);
84-
8594
}
8695
catch (InvocationTargetException ex) {
8796
throw new IllegalStateException("WebSphere addPreDefinePlugin method threw exception", ex.getCause());
@@ -93,9 +102,9 @@ public void addTransformer(ClassFileTransformer transformer) {
93102

94103
public ClassLoader getThrowawayClassLoader() {
95104
try {
96-
ClassLoader loader = cloneConstructor.newInstance(getClassLoader());
97-
// clear out the transformers (copied as well)
98-
List<?> list = (List<?>) transformerList.get(loader);
105+
ClassLoader loader = this.cloneConstructor.newInstance(getClassLoader());
106+
// Clear out the transformers (copied as well)
107+
List<?> list = (List<?>) this.transformerList.get(loader);
99108
list.clear();
100109
return loader;
101110
}

spring-context/src/main/java/org/springframework/instrument/classloading/websphere/WebSphereLoadTimeWeaver.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818

1919
import java.lang.instrument.ClassFileTransformer;
2020

21+
import org.springframework.core.OverridingClassLoader;
2122
import org.springframework.instrument.classloading.LoadTimeWeaver;
2223
import org.springframework.util.Assert;
2324
import org.springframework.util.ClassUtils;
@@ -67,7 +68,8 @@ public ClassLoader getInstrumentableClassLoader() {
6768

6869
@Override
6970
public ClassLoader getThrowawayClassLoader() {
70-
return this.classLoader.getThrowawayClassLoader();
71+
return new OverridingClassLoader(this.classLoader.getClassLoader(),
72+
this.classLoader.getThrowawayClassLoader());
7173
}
7274

7375
}

spring-core/src/main/java/org/springframework/core/DecoratingClassLoader.java

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,8 +16,9 @@
1616

1717
package org.springframework.core;
1818

19-
import java.util.HashSet;
19+
import java.util.Collections;
2020
import java.util.Set;
21+
import java.util.concurrent.ConcurrentHashMap;
2122

2223
import org.springframework.lang.UsesJava7;
2324
import org.springframework.util.Assert;
@@ -49,11 +50,11 @@ public abstract class DecoratingClassLoader extends ClassLoader {
4950
}
5051

5152

52-
private final Set<String> excludedPackages = new HashSet<String>();
53+
private final Set<String> excludedPackages =
54+
Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(8));
5355

54-
private final Set<String> excludedClasses = new HashSet<String>();
55-
56-
private final Object exclusionMonitor = new Object();
56+
private final Set<String> excludedClasses =
57+
Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(8));
5758

5859

5960
/**
@@ -79,9 +80,7 @@ public DecoratingClassLoader(ClassLoader parent) {
7980
*/
8081
public void excludePackage(String packageName) {
8182
Assert.notNull(packageName, "Package name must not be null");
82-
synchronized (this.exclusionMonitor) {
83-
this.excludedPackages.add(packageName);
84-
}
83+
this.excludedPackages.add(packageName);
8584
}
8685

8786
/**
@@ -92,9 +91,7 @@ public void excludePackage(String packageName) {
9291
*/
9392
public void excludeClass(String className) {
9493
Assert.notNull(className, "Class name must not be null");
95-
synchronized (this.exclusionMonitor) {
96-
this.excludedClasses.add(className);
97-
}
94+
this.excludedClasses.add(className);
9895
}
9996

10097
/**
@@ -107,15 +104,13 @@ public void excludeClass(String className) {
107104
* @see #excludeClass
108105
*/
109106
protected boolean isExcluded(String className) {
110-
synchronized (this.exclusionMonitor) {
111-
if (this.excludedClasses.contains(className)) {
107+
if (this.excludedClasses.contains(className)) {
108+
return true;
109+
}
110+
for (String packageName : this.excludedPackages) {
111+
if (className.startsWith(packageName)) {
112112
return true;
113113
}
114-
for (String packageName : this.excludedPackages) {
115-
if (className.startsWith(packageName)) {
116-
return true;
117-
}
118-
}
119114
}
120115
return false;
121116
}

0 commit comments

Comments
 (0)