Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8268554

com.sun.beans.introspect.ClassInfo leaks classes in cache.

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P4 P4
    • tbd
    • 11
    • client-libs
    • None

      ClassInfo keeps classes in SoftReferences which is unreasonable.
      When a Class is no longer reachable, there is no reason to keep it until the memory runs out.
      A Weak Key is therefore sufficent.
      A Weak Value would probably also be more reasonable, but that's discussable, contrary to the key.

      Probably, other useages of com.sun.beans.util.Cache might have similar issues

      Workaround is to change the reference type via reflection.

          protected Field makeFinalFieldAccessible(Field field) throws Exception {
              field.setAccessible(true);

              Field modifiersField = Field.class.getDeclaredField("modifiers");
              modifiersField.setAccessible(true);
              modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
              return field;
          }

          protected void fixLeakInBeansCache() {
              try {
                  Class classinfo = getClass().getClassLoader().loadClass("com.sun.beans.introspect.ClassInfo");
                  Field cacheField = classinfo.getDeclaredField("CACHE");
                  cacheField.setAccessible(true);
                  //cacheField.setInt(cacheField, cacheField.getModifiers() & ~Modifier.FINAL/* & ~Modifier.PRIVATE*/);
                  Object cache = cacheField.get(null);

                  Class kind = getClass().getClassLoader().loadClass("com.sun.beans.util.Cache$Kind");
                  Object weak = kind.getDeclaredField("WEAK").get(null);

                  System.out.println("Cache: " + cache);
                  System.out.println("kind: " + kind);

                  Field field1 = makeFinalFieldAccessible(cache.getClass().getSuperclass().getDeclaredField("keyKind"));
                  Field field2 = makeFinalFieldAccessible(cache.getClass().getSuperclass().getDeclaredField("valueKind"));
                  field1.set(cache,weak);
                  field2.set(cache,weak);


                  Field crfField = ConcurrentReferenceHashMap.class.getDeclaredField("DEFAULT_REFERENCE_TYPE");

                  makeFinalFieldAccessible(crfField);
                  crfField.set(null, ConcurrentReferenceHashMap.ReferenceType.WEAK);

              } catch(Exception e) {
                  throw new RuntimeException(e);
              }
          }

            Unassigned Unassigned
            fkirmaier Florian Kirmaier
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: