Skip to content

Use String.intern() for Annotation and Class scanning [SPR-14862] #19428

Closed
@spring-projects-issues

Description

@spring-projects-issues

Renier Roth opened SPR-14862 and commented

Consider Using String.intern() on the Type scanned by the Visitors. These Strings are always identical but are duplicated in Memory cause of new String() call.

Class: org.springframework.asm.Type
Line 565 & 580

example:
{CODE:linenumbers=true}
/**

  • Returns the binary name of the class corresponding to this type. This

  • method must not be used on method types.

  • @return the binary name of the class corresponding to this type.
    */
    public String getClassName() {
    switch (sort) {
    case VOID:
    return "void";
    case BOOLEAN:
    return "boolean";
    case CHAR:
    return "char";
    case BYTE:
    return "byte";
    case SHORT:
    return "short";
    case INT:
    return "int";
    case FLOAT:
    return "float";
    case LONG:
    return "long";
    case DOUBLE:
    return "double";
    case ARRAY:
    StringBuilder sb = new StringBuilder(getElementType().getClassName());
    for (int i = getDimensions(); i > 0; --i) {
    sb.append("[]");
    }
    return sb.toString();
    case OBJECT:
    return new String(buf, off, len).replace('/', '.');
    default:
    return null;
    }
    }

    /**

    • Returns the internal name of the class corresponding to this object or
    • array type. The internal name of a class is its fully qualified name (as
    • returned by Class.getName(), where '.' are replaced by '/'. This method
    • should only be used for an object or array type.
    • @return the internal name of the class corresponding to this object type.
      */
      public String getInternalName() {
      return new String(buf, off, len);
      }

{CODE}

Changed to:
{CODE:linenumbers=true}
/**

  • Returns the binary name of the class corresponding to this type. This

  • method must not be used on method types.

  • @return the binary name of the class corresponding to this type.
    */
    public String getClassName() {
    switch (sort) {
    case VOID:
    return "void";
    case BOOLEAN:
    return "boolean";
    case CHAR:
    return "char";
    case BYTE:
    return "byte";
    case SHORT:
    return "short";
    case INT:
    return "int";
    case FLOAT:
    return "float";
    case LONG:
    return "long";
    case DOUBLE:
    return "double";
    case ARRAY:
    StringBuilder sb = new StringBuilder(getElementType().getClassName());
    for (int i = getDimensions(); i > 0; --i) {
    sb.append("[]");
    }
    return sb.toString();
    case OBJECT:
    return new String(buf, off, len).replace('/', '.').intern();
    default:
    return null;
    }
    }

    /**

    • Returns the internal name of the class corresponding to this object or
    • array type. The internal name of a class is its fully qualified name (as
    • returned by Class.getName(), where '.' are replaced by '/'. This method
    • should only be used for an object or array type.
    • @return the internal name of the class corresponding to this object type.
      */
      public String getInternalName() {
      return new String(buf, off, len).intern();
      }

{CODE}
Lines difference in 34 & 49

This is used by several visitors on Class/Annotation scanning. The names of these Classes are then cached, but uses a new String Reference in Memory.

By Using String.intern() we can avoid duplicated Strings.
Memory Consumption and count of duplicated Strings depends on How many Annotations you have in your managed Beans.


Affects: 4.3.3

Issue Links:

Referenced from: commits d859826, 61d7d16

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)type: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions