Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java 11 compatibility: Try getting fields by Unsafe in ObjectGraphWalker #65

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 38 additions & 16 deletions src/main/java/org/ehcache/sizeof/ObjectGraphWalker.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
*/
package org.ehcache.sizeof;

import sun.misc.Unsafe;
import org.ehcache.sizeof.filters.SizeOfFilter;
import org.ehcache.sizeof.impl.UnsafeSizeOf;
import org.ehcache.sizeof.util.WeakIdentityConcurrentMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -157,11 +159,7 @@ long walk(VisitorListener visitorListener, Object... root) {
}
} else {
for (Field field : getFilteredFields(refClass)) {
try {
nullSafeAdd(toVisit, field.get(ref));
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
}
nullSafeAdd(toVisit, getNonPrimitiveValue(ref, field));
}
}

Expand Down Expand Up @@ -241,24 +239,48 @@ private static Collection<Field> getAllFields(Class<?> refClass) {
for (Field field : klazz.getDeclaredFields()) {
if (!Modifier.isStatic(field.getModifiers()) &&
!field.getType().isPrimitive()) {
try {
field.setAccessible(true);
} catch (SecurityException e) {
LOG.error("Security settings prevent Ehcache from accessing the subgraph beneath '{}'" +
" - cache sizes may be underestimated as a result", field, e);
continue;
} catch (RuntimeException e) {
LOG.warn("The JVM is preventing Ehcache from accessing the subgraph beneath '{}'" +
" - cache sizes may be underestimated as a result", field, e);
continue;
}
fields.add(field);
}
}
}
return fields;
}

/**
* Returns the value of the non-primitive field in the given instance.
* Should be used with {@link #getAllFields} to make sure the field is non-static and non-primitive.
*
* @param ref instance to get field value from
* @param field field descriptor
* @return the value object. null if we fail to get the value.
*/
private static Object getNonPrimitiveValue(Object ref, Field field) {
Unsafe unsafe = UnsafeSizeOf.getUnsafe();
boolean noUnsafe = unsafe == null;
try {
field.setAccessible(true);
return field.get(ref);
} catch (SecurityException e) {
if (noUnsafe) {
LOG.error("Security settings prevent Ehcache from accessing the subgraph beneath '{}'" +
" - cache sizes may be underestimated as a result", field, e);
return null;
}
} catch (RuntimeException e) {
if (noUnsafe) {
LOG.warn("The JVM is preventing Ehcache from accessing the subgraph beneath '{}'" +
" - cache sizes may be underestimated as a result", field, e);
return null;
}
} catch (IllegalAccessException e) {
if (noUnsafe) {
throw new RuntimeException(e);
}
}
long offset = unsafe.objectFieldOffset(field);
return unsafe.getObject(ref, offset);
}

private boolean byPassIfFlyweight(Object obj) {
if(bypassFlyweight) {
FlyweightType type = FlyweightType.getFlyweightType(obj.getClass());
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/org/ehcache/sizeof/impl/UnsafeSizeOf.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ public class UnsafeSizeOf extends SizeOf {
UNSAFE = unsafe;
}

public static Unsafe getUnsafe() {
return UNSAFE;
}

/**
* Builds a new SizeOf that will not filter fields and will cache reflected fields
*
Expand Down