Skip to content

Java enumerations should *cache* the field values #11856

Description

@jonpryor

Consider the Thread.State enum:

/* partial */classThread {
publicstaticfinal/* partial */enumState {
NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED
}
}

This "actually" is a class with fields for each enum value:

% javap java.lang.Thread.StateCompiled from "Thread.java"public final class java.lang.Thread$State extends java.lang.Enum<java.lang.Thread$State> { public static final java.lang.Thread$State NEW; public static final java.lang.Thread$State RUNNABLE; public static final java.lang.Thread$State BLOCKED; public static final java.lang.Thread$State WAITING; public static final java.lang.Thread$State TIMED_WAITING; public static final java.lang.Thread$State TERMINATED; public static java.lang.Thread$State[] values(); public static java.lang.Thread$State valueOf(java.lang.String); static {};}

When we bind it, we bind the fields as properties:

https://github.com/dotnet/java-interop/blob/fcad3368815dffd0f38f64384aa21b0b65367d68/src/Java.Base-ref.cs#L5490-L5506

However, each of those properties involves a ValueManager lookup:

namespaceJava.Lang{publicpartialclassThread{publicsealedpartialclassState:global::Java.Lang.Enum{publicstaticglobal::Java.Lang.Thread.State?Runnable{get{conststring__id="RUNNABLE.Ljava/lang/Thread$State;";var__v=_members.StaticFields.GetObjectValue(__id);returnglobal::Java.Interop.JniEnvironment.Runtime.ValueManager.GetValue<global::Java.Lang.Thread.State?>(ref__v,JniObjectReferenceOptions.Copy);}}}}}

This is JavaInterop1, not XAJavaInterop1, but .NET for Android isn't much different:

publicstaticJava.Lang.Thread.State?Runnable{get{conststring__id="RUNNABLE.Ljava/lang/Thread$State;";var__v=_members.StaticFields.GetObjectValue(__id);returnglobal::Java.Lang.Object.GetObject<Java.Lang.Thread.State>(__v.Handle,JniHandleOwnership.TransferLocalRef);}}

The problem is that value lookup is not fast -- identity hash code needs to be obtained, locks obtained, etc. -- to the point that repeated enum lookups can actually show up in profiles.

TODO: @jonathanpeppers, please provide your profile data. :-D

Suggestion: could we update property generation for all final fields to cache the return value? This means we'd only need to call StaticFields.GetObjectValue() and "GetValue" once, instead of once per-access:

global::Java.Lang.Thread.State?_Runnable_cache;publicstaticglobal::Java.Lang.Thread.State?Runnable{get{if(_Runnable_cache!=null)return_Runnable_cache;conststring__id="RUNNABLE.Ljava/lang/Thread$State;";var__v=_members.StaticFields.GetObjectValue(__id);return_Runnable_cache=global::Java.Interop.JniEnvironment.Runtime.ValueManager.GetValue<global::Java.Lang.Thread.State?>(ref__v,JniObjectReferenceOptions.Copy);}}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area: BindingsIssues in Java Library Binding projects.java-interopIssues migrated from dotnet/java-interop / relates to the Java.Interop subtreeneeds-triageIssues that need to be assigned.possibly-staleIssues that are potentially no longer relevant.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions