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

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

    XMLWordPrintable

Details

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

    Description

      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);
              }
          }

      Attachments

        Issue Links

          Activity

            People

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

              Dates

                Created:
                Updated: