You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by no...@apache.org on 2017/01/24 08:58:15 UTC
[10/10] lucene-solr:apiv2: fixing merge errors
fixing merge errors
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/8d05282b
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/8d05282b
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/8d05282b
Branch: refs/heads/apiv2
Commit: 8d05282be4a1c5cc02084f665a16ef6b897f2ac8
Parents: 8999015
Author: Noble Paul <no...@apache.org>
Authored: Tue Jan 24 19:27:30 2017 +1030
Committer: Noble Paul <no...@apache.org>
Committed: Tue Jan 24 19:27:30 2017 +1030
----------------------------------------------------------------------
.../org/apache/lucene/util/RamUsageTester.java | 96 +++++++++++++++++---
1 file changed, 83 insertions(+), 13 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d05282b/lucene/test-framework/src/java/org/apache/lucene/util/RamUsageTester.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/util/RamUsageTester.java b/lucene/test-framework/src/java/org/apache/lucene/util/RamUsageTester.java
index 2c6e245..337d4be 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/util/RamUsageTester.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/util/RamUsageTester.java
@@ -16,9 +16,12 @@
*/
package org.apache.lucene.util;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
+import java.nio.file.Path;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.AbstractList;
@@ -30,6 +33,10 @@ import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.function.ToLongFunction;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
/** Crawls object graph to collect RAM usage for testing */
public final class RamUsageTester {
@@ -40,9 +47,7 @@ public final class RamUsageTester {
/** Accumulate transitive references for the provided fields of the given
* object into <code>queue</code> and return the shallow size of this object. */
public long accumulateObject(Object o, long shallowSize, Map<Field, Object> fieldValues, Collection<Object> queue) {
- for (Object value : fieldValues.values()) {
- queue.add(value);
- }
+ queue.addAll(fieldValues.values());
return shallowSize;
}
@@ -130,10 +135,10 @@ public final class RamUsageTester {
@Override
public int size() {
return len;
- }
+ }
- };
- }
+ };
+ }
totalSize += accumulator.accumulateArray(ob, shallowSize, values, stack);
} else {
/*
@@ -146,12 +151,35 @@ public final class RamUsageTester {
classCache.put(obClazz, cachedInfo = createCacheEntry(obClazz));
}
- Map<Field, Object> fieldValues = new HashMap<>();
- for (Field f : cachedInfo.referenceFields) {
- fieldValues.put(f, f.get(ob));
+ boolean needsReflection = true;
+ if (Constants.JRE_IS_MINIMUM_JAVA9 && obClazz.getName().startsWith("java.")) {
+ // Java 9: Best guess for some known types, as we cannot precisely look into runtime classes:
+ final ToLongFunction<Object> func = SIMPLE_TYPES.get(obClazz);
+ if (func != null) { // some simple type like String where the size is easy to get from public properties
+ totalSize += accumulator.accumulateObject(ob, cachedInfo.alignedShallowInstanceSize + func.applyAsLong(ob),
+ Collections.emptyMap(), stack);
+ needsReflection = false;
+ } else if (ob instanceof Iterable) {
+ final List<Object> values = StreamSupport.stream(((Iterable<?>) ob).spliterator(), false)
+ .collect(Collectors.toList());
+ totalSize += accumulator.accumulateArray(ob, cachedInfo.alignedShallowInstanceSize + RamUsageEstimator.NUM_BYTES_ARRAY_HEADER, values, stack);
+ needsReflection = false;
+ } else if (ob instanceof Map) {
+ final List<Object> values = ((Map<?,?>) ob).entrySet().stream()
+ .flatMap(e -> Stream.of(e.getKey(), e.getValue()))
+ .collect(Collectors.toList());
+ totalSize += accumulator.accumulateArray(ob, cachedInfo.alignedShallowInstanceSize + RamUsageEstimator.NUM_BYTES_ARRAY_HEADER, values, stack);
+ totalSize += RamUsageEstimator.NUM_BYTES_ARRAY_HEADER;
+ needsReflection = false;
+ }
+ }
+ if (needsReflection) {
+ final Map<Field, Object> fieldValues = new HashMap<>();
+ for (Field f : cachedInfo.referenceFields) {
+ fieldValues.put(f, f.get(ob));
+ }
+ totalSize += accumulator.accumulateObject(ob, cachedInfo.alignedShallowInstanceSize, fieldValues, stack);
}
-
- totalSize += accumulator.accumulateObject(ob, cachedInfo.alignedShallowInstanceSize, fieldValues, stack);
} catch (IllegalAccessException e) {
// this should never happen as we enabled setAccessible().
throw new RuntimeException("Reflective field access failed?", e);
@@ -167,6 +195,40 @@ public final class RamUsageTester {
return totalSize;
}
+ /**
+ * This map contains a function to calculate sizes of some "simple types" like String just from their public properties.
+ * This is needed for Java 9, which does not allow to look into runtime class fields.
+ */
+ @SuppressWarnings("serial")
+ private static final Map<Class<?>, ToLongFunction<Object>> SIMPLE_TYPES = Collections.unmodifiableMap(new IdentityHashMap<Class<?>, ToLongFunction<Object>>() {
+ { init(); }
+
+ @SuppressForbidden(reason = "We measure some forbidden classes")
+ private void init() {
+ // String types:
+ a(String.class, v -> charArraySize(v.length())); // may not be correct with Java 9's compact strings!
+ a(StringBuilder.class, v -> charArraySize(v.capacity()));
+ a(StringBuffer.class, v -> charArraySize(v.capacity()));
+ // Types with large buffers:
+ a(ByteArrayOutputStream.class, v -> byteArraySize(v.size()));
+ // For File and Path, we just take the length of String representation as approximation:
+ a(File.class, v -> charArraySize(v.toString().length()));
+ a(Path.class, v -> charArraySize(v.toString().length()));
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T> void a(Class<T> clazz, ToLongFunction<T> func) {
+ put(clazz, (ToLongFunction<Object>) func);
+ }
+
+ private long charArraySize(int len) {
+ return RamUsageEstimator.alignObjectSize((long)RamUsageEstimator.NUM_BYTES_ARRAY_HEADER + (long)Character.BYTES * len);
+ }
+
+ private long byteArraySize(int len) {
+ return RamUsageEstimator.alignObjectSize((long)RamUsageEstimator.NUM_BYTES_ARRAY_HEADER + len);
+ }
+ });
/**
* Cached information about a given class.
@@ -202,8 +264,16 @@ public final class RamUsageTester {
shallowInstanceSize = RamUsageEstimator.adjustForField(shallowInstanceSize, f);
if (!f.getType().isPrimitive()) {
- f.setAccessible(true);
- referenceFields.add(f);
+ try {
+ f.setAccessible(true);
+ referenceFields.add(f);
+ } catch (RuntimeException re) {
+ if ("java.lang.reflect.InaccessibleObjectException".equals(re.getClass().getName())) {
+ // LUCENE-7595: this is Java 9, which prevents access to fields in foreign modules
+ } else {
+ throw re;
+ }
+ }
}
}
}