This is some pretty deeply nested code, and I'm not sure I like the idea of having the hex string test logic duplicated here.

What about this alternative implementation?

  String[] fanout = objects.list();
  if (fanout == null)
    fanout = new String[0];

  for (String d : fanout) {
    if (d.length() != 2)
      continue;

    String[] entries = new File(objects, d).list();
    if (entries == null)
      continue;

    for (String e : entries) {
      if (e.length() != Constants.OBJECT_ID_STRING_LENGTH - 2)
        continue;

      try {
        unpackedObjects.add(ObjectId.fromString(d + e));
      } catch (IllegalArgumentException notAnObject) {
      }
    }
  }

The odds of finding a non-hex file inside of a loose object directory is incredibly low, especially once you include the test for length = 38 like we do at the start of the loop.  So we are very unlikely to throw an exception during the scan.