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

Crash Every Day on Android M! java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object) #324

Closed
Jacksgong opened this issue Nov 12, 2015 · 3 comments

Comments

@Jacksgong
Copy link

  • Android M
  • Nexus 5
  • targetSdkVersion 23
  • compileSdkVersion 23
  • multiDexEnabled true

Crash every day:

1.3.1:

 if (/** npe here!!!! **/keyCandidate.equals(key)) {
        return (IObject) weakRef.resolveValue("referent");
      }

Detail:

// HeapAnalyzer#findLeakingReference by 1.3.1
private IObject findLeakingReference(String key, ISnapshot snapshot) throws SnapshotException {
    Collection<IClass> refClasses =
        snapshot.getClassesByName(KeyedWeakReference.class.getName(), false);

    if (refClasses.size() != 1) {
      throw new IllegalStateException(
          "Expecting one class for " + KeyedWeakReference.class.getName() + " in " + refClasses);
    }

    IClass refClass = refClasses.iterator().next();

    int[] weakRefInstanceIds = refClass.getObjectIds();

    for (int weakRefInstanceId : weakRefInstanceIds) {
      IObject weakRef = snapshot.getObject(weakRefInstanceId);
      String keyCandidate =
          PrettyPrinter.objectAsString((IObject) weakRef.resolveValue("key"), 100);
      if (/** npe here **/keyCandidate.equals(key)) {
        return (IObject) weakRef.resolveValue("referent");
      }
    }
    throw new IllegalStateException("Could not find weak reference with key " + key);
  }

// PrettyPrinter.objectAsString by 1.3.1
public static String objectAsString(IObject stringObject, int limit) throws SnapshotException {
    Integer count = (Integer) stringObject.resolveValue("count"); 
    if (count == null) return null;
    if (count.intValue() == 0) return ""; 

    IPrimitiveArray charArray = (IPrimitiveArray) stringObject.resolveValue("value"); 
    if (charArray == null) return null; // return null

    Integer offset = (Integer) stringObject.resolveValue("offset"); 
    if (offset == null) return null; // return null!

    return arrayAsString(charArray, offset, count, limit);
  }

public static String arrayAsString(IPrimitiveArray charArray, int offset, int count, int limit) {
    if (charArray.getType() != IObject.Type.CHAR) return null; // return null

    int length = charArray.getLength();

    int contentToRead = count <= limit ? count : limit;
    if (contentToRead > length - offset) contentToRead = length - offset;

    char[] value;
    if (offset == 0 && length == contentToRead) {
      value = (char[]) charArray.getValueArray();
    } else {
      value = (char[]) charArray.getValueArray(offset, contentToRead);
    }

    if (value == null) return null; // return null

    StringBuilder result = new StringBuilder(value.length);
    for (int ii = 0; ii < value.length; ii++) {
      char val = value[ii];
      if (val >= 32 && val < 127) {
        result.append(val);
      } else {
        result.append("\\u").append(String.format("%04x", 0xFFFF & val)); 
      }
    }
    if (limit < count) result.append("..."); //$NON-NLS-1$
    return result.toString();
  }

  private PrettyPrinter() {
  }
@Jacksgong Jacksgong changed the title Crash Every Day in Android M! java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object) Crash Every Day on Android M! java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object) Nov 12, 2015
@Jacksgong
Copy link
Author

Last code on master branch fix such npe, but not release... and When?

private Instance findLeakingReference(String key, Snapshot snapshot) {
    ClassObj refClass = snapshot.findClass(KeyedWeakReference.class.getName());
    List<String> keysFound = new ArrayList<>();
    for (Instance instance : refClass.getInstancesList()) {
      List<ClassInstance.FieldValue> values = classInstanceValues(instance);
      String keyCandidate = asString(fieldValue(values, "key"));
      if (keyCandidate.equals(key)) {
        return fieldValue(values, "referent");
      }
      keysFound.add(keyCandidate);
    }
    throw new IllegalStateException(
        "Could not find weak reference with key " + key + " in " + keysFound);
  }

static String asString(Object stringObject) {
    Instance instance = (Instance) stringObject;
    List<ClassInstance.FieldValue> values = classInstanceValues(instance);

    Integer count = fieldValue(values, "count");
    Object value = fieldValue(values, "value");
    Integer offset;
    ArrayInstance charArray;
    if (isCharArray(value)) {
      charArray = (ArrayInstance) value;
      offset = fieldValue(values, "offset");
    } else {
      // In M preview 2+, the underlying char buffer resides in the heap with ID equalling the
      // String's ID + 16.
      // https://android-review.googlesource.com/#/c/160380/2/android/src/com/android/tools/idea/
      // editors/hprof/descriptors/InstanceFieldDescriptorImpl.java
      Heap heap = instance.getHeap();
      Instance inlineInstance = heap.getInstance(instance.getId() + 16);
      if (isCharArray(inlineInstance)) {
        charArray = (ArrayInstance) inlineInstance;
        offset = 0;
      } else {
        throw new UnsupportedOperationException("Could not find char array in " + instance);
      }
    }
    checkNotNull(count, "count");
    checkNotNull(charArray, "charArray");
    checkNotNull(offset, "offset");

    if (count == 0) {
      return "";
    }

    char[] chars = charArray.asCharArray(offset, count);

    return new String(chars);
  }

@cristiangarciascmspain
Copy link

another issue related to #267

@jrodbx
Copy link
Collaborator

jrodbx commented Jan 2, 2016

Duplicate of #341

@jrodbx jrodbx closed this as completed Jan 2, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants