Skip to content

Commit 54f1e6c

Browse files
committed
Reuse existing Groovy reflection data. Reduces memory footprint.
1 parent 94ea602 commit 54f1e6c

File tree

1 file changed

+41
-39
lines changed

1 file changed

+41
-39
lines changed

grails-core/src/main/groovy/org/grails/core/util/ClassPropertyFetcher.java

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,25 @@
1515
*/
1616
package org.grails.core.util;
1717

18-
import java.beans.PropertyDescriptor;
19-
import java.lang.reflect.Field;
20-
import java.lang.reflect.InvocationTargetException;
21-
import java.lang.reflect.Method;
22-
import java.lang.reflect.Modifier;
23-
import java.util.*;
24-
import java.util.concurrent.ConcurrentHashMap;
25-
2618
import grails.util.GrailsClassUtils;
27-
import grails.util.GrailsNameUtils;
2819
import groovy.lang.GroovyObjectSupport;
2920
import groovy.lang.Script;
21+
import org.codehaus.groovy.reflection.CachedClass;
22+
import org.codehaus.groovy.reflection.CachedField;
23+
import org.codehaus.groovy.reflection.CachedMethod;
24+
import org.codehaus.groovy.reflection.ClassInfo;
3025
import org.springframework.beans.BeanUtils;
31-
import org.springframework.util.ReflectionUtils;
32-
import org.springframework.util.ReflectionUtils.FieldCallback;
33-
import org.springframework.util.ReflectionUtils.MethodCallback;
3426
import org.springframework.util.StringUtils;
3527

28+
import java.beans.PropertyDescriptor;
29+
import java.lang.reflect.InvocationTargetException;
30+
import java.lang.reflect.Modifier;
31+
import java.util.HashMap;
32+
import java.util.HashSet;
33+
import java.util.Map;
34+
import java.util.Set;
35+
import java.util.concurrent.ConcurrentHashMap;
36+
3637
/**
3738
* Accesses class "properties": static fields, static getters, instance fields
3839
* or instance getters.
@@ -96,11 +97,8 @@ public Object getReferenceInstance() {
9697
protected ClassPropertyFetcher(Class<?> clazz, ReferenceInstanceCallback callback) {
9798
this.clazz = clazz;
9899
this.callback = callback;
99-
fieldCallback = new ReflectionUtils.FieldCallback() {
100-
public void doWith(Field field) {
101-
if (field.isSynthetic()) {
102-
return;
103-
}
100+
fieldCallback = new FieldCallback() {
101+
public void doWith(CachedField field) {
104102
final int modifiers = field.getModifiers();
105103
if (!Modifier.isPublic(modifiers)) {
106104
return;
@@ -120,16 +118,12 @@ public void doWith(Field field) {
120118
}
121119
};
122120

123-
methodCallback = new ReflectionUtils.MethodCallback() {
124-
public void doWith(Method method) throws IllegalArgumentException,
121+
methodCallback = new MethodCallback() {
122+
public void doWith(CachedMethod method) throws IllegalArgumentException,
125123
IllegalAccessException {
126-
if (method.isSynthetic()) {
127-
return;
128-
}
129-
int modifiers = method.getModifiers();
130124
Class<?> returnType = method.getReturnType();
131125

132-
if (!Modifier.isPublic(modifiers)) {
126+
if (!method.isPublic()) {
133127
return;
134128
}
135129
if (returnType != Void.class && returnType != void.class) {
@@ -146,7 +140,7 @@ public void doWith(Method method) throws IllegalArgumentException,
146140
returnType == boolean.class)) {
147141
name = name.substring(2);
148142
}
149-
if (Modifier.isStatic(modifiers)) {
143+
if (method.isStatic()) {
150144
GetterPropertyFetcher fetcher = new GetterPropertyFetcher(method, true);
151145
staticFetchers.put(name, fetcher);
152146
staticFetchers.put(StringUtils.uncapitalize(name),
@@ -180,6 +174,7 @@ public boolean isReadableProperty(String name) {
180174
}
181175

182176
private void init() {
177+
ClassInfo classInfo = ClassInfo.getClassInfo(clazz);
183178
Class<?> superclass = clazz.getSuperclass();
184179
while (superclass != Object.class && superclass != Script.class && superclass != GroovyObjectSupport.class && superclass != null) {
185180
ClassPropertyFetcher superFetcher = ClassPropertyFetcher.forClass(superclass);
@@ -188,8 +183,9 @@ private void init() {
188183
superclass = superclass.getSuperclass();
189184
}
190185

191-
Field[] fields = clazz.getDeclaredFields();
192-
for (Field field : fields) {
186+
CachedClass cachedClass = classInfo.getCachedClass();
187+
CachedField[] fields = cachedClass.getFields();
188+
for (CachedField field : fields) {
193189
try {
194190
fieldCallback.doWith(field);
195191
} catch (IllegalAccessException ex) {
@@ -198,8 +194,8 @@ private void init() {
198194
+ field.getName() + "': " + ex);
199195
}
200196
}
201-
Method[] methods = clazz.getDeclaredMethods();
202-
for (Method method : methods) {
197+
CachedMethod[] methods = cachedClass.getMethods();
198+
for (CachedMethod method : methods) {
203199
try {
204200
methodCallback.doWith(method);
205201
} catch (IllegalAccessException ex) {
@@ -307,23 +303,23 @@ Object get(ReferenceInstanceCallback callback)
307303
}
308304

309305
static class GetterPropertyFetcher implements PropertyFetcher {
310-
private final Method readMethod;
306+
private static final Object[] ZERO_ARGS = new Object[0];
307+
private final CachedMethod readMethod;
311308
private final boolean staticMethod;
312309

313-
GetterPropertyFetcher(Method readMethod, boolean staticMethod) {
310+
GetterPropertyFetcher(CachedMethod readMethod, boolean staticMethod) {
314311
this.readMethod = readMethod;
315312
this.staticMethod = staticMethod;
316-
ReflectionUtils.makeAccessible(readMethod);
317313
}
318314

319315
public Object get(ReferenceInstanceCallback callback)
320316
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
321317
if (staticMethod) {
322-
return readMethod.invoke(null);
318+
return readMethod.invoke(null, ZERO_ARGS);
323319
}
324320

325321
if (callback != null) {
326-
return readMethod.invoke(callback.getReferenceInstance());
322+
return readMethod.invoke(callback.getReferenceInstance(), ZERO_ARGS);
327323
}
328324

329325
return null;
@@ -335,23 +331,22 @@ public Class<?> getPropertyType(String name) {
335331
}
336332

337333
static class FieldReaderFetcher implements PropertyFetcher {
338-
private final Field field;
334+
private final CachedField field;
339335
private final boolean staticField;
340336

341-
public FieldReaderFetcher(Field field, boolean staticField) {
337+
public FieldReaderFetcher(CachedField field, boolean staticField) {
342338
this.field = field;
343339
this.staticField = staticField;
344-
ReflectionUtils.makeAccessible(field);
345340
}
346341

347342
public Object get(ReferenceInstanceCallback callback)
348343
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
349344
if (staticField) {
350-
return field.get(null);
345+
return field.getProperty(null);
351346
}
352347

353348
if (callback != null) {
354-
return field.get(callback.getReferenceInstance());
349+
return field.getProperty(callback.getReferenceInstance());
355350
}
356351

357352
return null;
@@ -361,4 +356,11 @@ public Class<?> getPropertyType(String name) {
361356
return field.getType();
362357
}
363358
}
359+
360+
private interface FieldCallback {
361+
void doWith(CachedField field) throws IllegalAccessException;
362+
}
363+
private interface MethodCallback {
364+
void doWith(CachedMethod field) throws IllegalAccessException;
365+
}
364366
}

0 commit comments

Comments
 (0)