From 4dfe64e94f153ccd8db56bea7b8cdfb02e5bba08 Mon Sep 17 00:00:00 2001 From: Jesse Wilson Date: Thu, 12 Jan 2012 12:09:26 -0500 Subject: [PATCH] Provide detail when methods or fields exceed the limit. Here's what the new message looks like: trouble writing output: Too many fields: 88304; max is 65536. By package: 10 dalvik.annotation 278 dalvik.bytecode 81 dalvik.system 94 dalvik.system.profiler 111 java.awt.font 12 java.beans 322 java.io 519 java.lang 20 java.lang.annotation 13 java.lang.ref 72 java.lang.reflect 72 java.math ... Change-Id: Ieea7efb178522d9ac3cb10c5a6cfb453be3fd72d --- .../com/android/dx/dex/file/MemberIdsSection.java | 30 +++++++++++++++++++--- dx/src/com/android/dx/rop/cst/CstType.java | 19 +++++++++++++- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/dx/src/com/android/dx/dex/file/MemberIdsSection.java b/dx/src/com/android/dx/dex/file/MemberIdsSection.java index ec39b75cd..ee844d9de 100644 --- a/dx/src/com/android/dx/dex/file/MemberIdsSection.java +++ b/dx/src/com/android/dx/dex/file/MemberIdsSection.java @@ -17,6 +17,10 @@ package com.android.dx.dex.file; import com.android.dx.util.DexException; +import java.util.Formatter; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.atomic.AtomicInteger; /** * Member (field or method) refs list section of a {@code .dex} file. @@ -42,9 +46,7 @@ public abstract class MemberIdsSection extends UniformItemSection { int idx = 0; if (items().size() > MAX_MEMBERS) { - String memberType = this instanceof MethodIdsSection ? "methods" : "fields"; - throw new DexException("Too many " + memberType + ": " + items().size() - + "; max is " + MAX_MEMBERS); + throw new DexException(tooManyMembersMessage()); } for (Object i : items()) { @@ -52,4 +54,26 @@ public abstract class MemberIdsSection extends UniformItemSection { idx++; } } + + private String tooManyMembersMessage() { + Map membersByPackage = new TreeMap(); + for (Object member : items()) { + String packageName = ((MemberIdItem) member).getDefiningClass().getPackageName(); + AtomicInteger count = membersByPackage.get(packageName); + if (count == null) { + count = new AtomicInteger(); + membersByPackage.put(packageName, count); + } + count.incrementAndGet(); + } + + Formatter formatter = new Formatter(); + String memberType = this instanceof MethodIdsSection ? "methods" : "fields"; + formatter.format("Too many %s: %d; max is %d. By package:", + memberType, items().size(), MAX_MEMBERS); + for (Map.Entry entry : membersByPackage.entrySet()) { + formatter.format("%n%6d %s", entry.getValue().get(), entry.getKey()); + } + return formatter.toString(); + } } diff --git a/dx/src/com/android/dx/rop/cst/CstType.java b/dx/src/com/android/dx/rop/cst/CstType.java index 8624028aa..870fcb480 100644 --- a/dx/src/com/android/dx/rop/cst/CstType.java +++ b/dx/src/com/android/dx/rop/cst/CstType.java @@ -17,7 +17,6 @@ package com.android.dx.rop.cst; import com.android.dx.rop.type.Type; - import java.util.HashMap; /** @@ -229,4 +228,22 @@ public final class CstType extends TypedConstant { return descriptor; } + + /** + * Returns a human readable package name for this type, like "java.util". + * If this is an array type, this returns the package name of the array's + * component type. If this is a primitive type, this returns "default". + */ + public String getPackageName() { + // descriptor is a string like "[[Ljava/util/String;" + String descriptor = getDescriptor().getString(); + int lastSlash = descriptor.lastIndexOf('/'); + int lastLeftSquare = descriptor.lastIndexOf('['); // -1 unless this is an array + if (lastSlash == -1) { + return "default"; + } else { + // +2 to skip the '[' and the 'L' prefix + return descriptor.substring(lastLeftSquare + 2, lastSlash).replace('/', '.'); + } + } } -- 2.11.0