From forax at univ-mlv.fr Mon Jun 2 12:00:45 2025 From: forax at univ-mlv.fr (Remi Forax) Date: Mon, 2 Jun 2025 14:00:45 +0200 (CEST) Subject: JVM Runtime Parametric Type Support Message-ID: <1936578057.10052715.1748865645346.JavaMail.zimbra@univ-eiffel.fr> Hello, this is a small proposal to try start (re-start) discussions about what would be the minimal changes of the JVM spec enabling java.util collections to be specialized at runtime when value classes are used as type arguments (by example a List). regards, R?mi --- # Java Virtual Machine Specification Extension: Runtime Parametric Type Support ## 1. Introduction This specification defines extensions to the Java Virtual Machine to support runtime propagation of type arguments for parametric (generic) classes and methods. While maintaining full backward compatibility with existing bytecode, these extensions enable type arguments to be available at runtime through two primary mechanisms: method call side value and parametric class instantiation. ### 1.1 Goals - Propagate type arguments at runtime while preserving type erasure compilation - Maintain complete backward compatibility with existing bytecode - Support both parametric method calls and parametric class instantiation - Provide clean APIs for accessing runtime type information ### 1.2 Overview The specification introduces: - A method modifier for method supporting side value - Reuse the opcode wide to specify method call side value - An API method "currentSideValue" to get the side value associated to a method call inside the callee - A new class modifier for parametric class - A new opcode anew_parametric for parametric Class instantiation (to send the layout + metadata) - An API method "currentMetadata" to get the metadata inside a parametric class --- ## 2. Class File Format Extensions ### 2.1 Access Flags Two new access flags are introduced: #### 2.1.1 ACC_SIDE_VALUE (new_flag) - **Applicable to**: Methods - **Purpose**: Indicates that a method accepts a side value (type arguments) from callers - **Behavior**: Enables `wide` method calls and access to `currentSideValue()` within the method #### 2.1.2 ACC_PARAMETRIC (new_flag) - **Applicable to**: Classes - **Purpose**: Indicates that a class supports parametric instantiation - **Behavior**: Enables `anew_parametric` instruction and access to `currentMetadata()` ### 2.2 Flag Validation - Methods with `ACC_SIDE_VALUE` must be declared to handle side value parameters - Classes with `ACC_PARAMETRIC` must support the `LayoutHandle` interface for instantiation - These flags are ignored by JVM implementations that do not support this extension --- ## 3. Method Call Side Value ### 3.1 Concept Method call side value enable the passing of an object (type arguments) from a call site to the callee method at runtime. This mechanism simulates generic type parameter passing without modifying method signatures. ### 3.2 Method Declaration Methods that accept a side value must be marked with the `ACC_SIDE_VALUE` access flag: ```java // Conceptual representation public static ACC_SIDE_VALUE void message(String message) { Object sideValue = currentSideValue(); ... } ``` ### 3.3 Bytecode Instructions #### 3.3.1 Wide Prefix for Method Calls The `wide` instruction is extended to prefix method call instructions when side values are passed: **Syntax:** ``` wide ``` **Supported Instructions:** - `invokestatic` - `invokevirtual` - `invokespecial` - `invokeinterface` - `invokedynamic` #### 3.3.2 Stack Layout When using `wide` with method calls, an additional argument must be present on the stack: **Stack (top to bottom):** ``` [method arguments...] [side value (Object)] ``` **Example Bytecode:** ```bytecode ldc "TypeArgument" // Push side value ldc "hello" // Push method argument wide invokestatic Foo.message(Ljava/lang/String;)V ``` ### 3.4 Runtime Behavior #### 3.4.1 currentSideValue() Method **Signature:** `public static Object currentSideValue()` **Behavior:** - Returns the side value passed to the current method - Returns `null` if the method was called without `wide` - Must only be called within methods marked `ACC_SIDE_VALUE` **Exceptions:** - `LinkageError`: Thrown if called from a method not marked `ACC_SIDE_VALUE` #### 3.4.2 Call Resolution 1. When `wide` prefixes a method call, the JVM pops the side value from the stack 2. The side value is made available to the target method via `currentSideValue()` 3. The method call proceeds normally with remaining stack arguments 4. If the target method is not marked `ACC_SIDE_VALUE`, a `VerifyError` is thrown --- ## 4. Parametric Class Instantiation ### 4.1 Concept Parametric class instantiation allows objects to be created with associated type metadata that remains accessible throughout the object's lifetime. ### 4.2 Class Declaration Classes supporting parametric instantiation must be marked with the `ACC_PARAMETRIC` access flag and work with the `LayoutHandle` interface. ### 4.3 LayoutHandle Interface ```java public interface LayoutHandle { /** * Returns metadata associated with this layout. * Must be a pure function (no side effects, deterministic). */ Object getMetadata(); /** * Returns the restricted field type for the given field. * Must be a pure function (no side effects, deterministic). * * @param name field name * @param descriptor field descriptor * @return Restricted type information */ Restricted fieldType(String name, String descriptor); } ``` ### 4.4 anew_parametric Instruction #### 4.4.1 Specification **Opcode:** (new opcode) **Format:** ``` anew_parametric indexbyte1 indexbyte2 ``` **Stack:** - **Before:** `[layout_handle]` - **After:** `[objectref]` **Description:** Creates a new instance of the class referenced by the constant pool entry at index `(indexbyte1 << 8) | indexbyte2`. The class must be marked with `ACC_PARAMETRIC`. The `layout_handle` on the stack must implement `LayoutHandle`. #### 4.4.2 Runtime Behavior 1. Pop `layout_handle` from stack 2. Resolve class reference from constant pool 3. Verify class has `ACC_PARAMETRIC` flag 4. Create new instance of the class 5. Associate the `layout_handle` with the instance 6. Push object reference onto stack **Exceptions:** - `VerifyError`: If class is not marked `ACC_PARAMETRIC` ### 4.5 Runtime Metadata Access #### 4.5.1 currentMetadata() Method **Signature:** `public static Object currentMetadata()` **Behavior:** - Returns the metadata from the `LayoutHandle` used to create the current instance - Returns `null` if the instance was created with standard `anew` - Must only be called within classes marked `ACC_PARAMETRIC` **Exceptions:** - `LinkageError`: Thrown if called from a class not marked `ACC_PARAMETRIC` --- ## 5. Verification and Linking ### 5.1 Class File Verification #### 5.1.1 ACC_SIDE_VALUE Methods - `currentSideValue()` calls must only appear in `ACC_SIDE_VALUE` methods #### 5.1.2 ACC_PARAMETRIC Classes - `currentMetadata()` calls must only appear in `ACC_PARAMETRIC` classes ### 5.2 Linking Requirements #### 5.2.1 Method Resolution - `wide` prefixed calls must resolve to valid method references with `ACC_SIDE_VALUE` flag - Side value compatibility is checked at call time, not link time #### 5.2.2 Class Resolution - `anew_parametric` must reference classes with `ACC_PARAMETRIC` flag - `LayoutHandle` implementation must be verified at instantiation time --- ## 6. Backward Compatibility ### 6.1 Bytecode Compatibility - All existing bytecode continues to work unchanged ### 6.2 Runtime Compatibility - `currentSideValue()` returns `null` if the method is called without the `wide` prefix. - `currentMetadata()` returns `null` if the object is instantiated without `anew_parametric` --- ## 8. Examples ### 8.1 Method Call Side Value Example ```java // Method declaration (conceptual) public static ACC_SIDE_VALUE void printType(Object value) { Object typeInfo = currentSideValue(); System.out.println("Value: " + value + ", Type: " + typeInfo); } // Bytecode usage ldc String.class // Type argument ldc "Hello World" // Method argument wide invokestatic Example.printType(Ljava/lang/Object;)V ``` ### 8.2 Parametric Class Example ```java // Class declaration (conceptual) public class ACC_PARAMETRIC Container { public void setValue(Object value) { Object metadata = currentMetadata(); System.out.println("Value: " + value + ", Metadata: " + metadata); } } // Bytecode usage ldc ConstantDynamic MyLayoutHandle // Get the layout handle anew_parametric Container ``` --- ## 9. Formal Grammar Extensions ### 9.1 Method Call Instructions ``` method_call_instruction ::= [wide] (invokestatic | invokevirtual | invokespecial | invokeinterface | invokedynamic) indexbyte1 indexbyte2 wide_method_call ::= wide method_call_opcode indexbyte1 indexbyte2 ``` ### 9.2 Object Creation Instructions ``` object_creation_instruction ::= anew indexbyte1 indexbyte2 | anew_parametric indexbyte1 indexbyte2 ``` --- ## 10. Conclusion This specification extends the Java Virtual Machine to support runtime parametric type propagation while maintaining complete backward compatibility. The two-mechanism approach (method call side values and parametric class instantiation) provides comprehensive support for runtime generic type information without breaking existing code or requiring recompilation of legacy applications. The design prioritizes backward compatibility and simplicity by transfering most the burden to JITs that must propagate the side value/metadata as constants across the method call graph. From daniel.smith at oracle.com Wed Jun 11 06:15:12 2025 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 11 Jun 2025 06:15:12 +0000 Subject: EG meeting *canceled*, 2025-06-11 Message-ID: <5B7B826D-E363-424B-AFA9-F2672E3B56F8@oracle.com> No meeting tomorrow, June 11. I've seen Remi's mail about specialization, but haven't had a chance to study it. If it's alright, let's plan on discussing that in 2 weeks (June 25), plus a status update on other Valhalla features. From brian.goetz at oracle.com Thu Jun 12 11:55:19 2025 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 12 Jun 2025 11:55:19 +0000 Subject: Fwd: Suggestion regarding Null State Analysis in Project Valhalla References: Message-ID: Received on the -comments list. Begin forwarded message: From: Abdurasul Abduraimov > Subject: Suggestion regarding Null State Analysis in Project Valhalla Date: June 12, 2025 at 1:06:49 AM EDT To: valhalla-spec-comments at openjdk.org Dear Team, I am a big fan of Java and I?m eagerly awaiting the release of Project Valhalla. I watched the Valhalla session from IntelliJ IDEA Conf 2025 (Day 1), where R?mi Forax discussed the "Null State Analysis" feature. As he explained, the system defines three null states: 1. Null-restricted: Integer! or String! 2. Nullable: Integer? or String? 3. Unspecified: Integer or String (with no warning) I understand that due to Java?s large amount of legacy code, introducing nullable and non-nullable types (as in Kotlin) is challenging, and the team is prioritizing backward compatibility. However, I?d like to propose an idea: What if the Unspecified state also emitted a warning? This way, all types would continue to be effectively nullable (as they are today), but developers upgrading to future Java versions (where Valhalla is finalized) would be encouraged to explicitly annotate their types. They could mark types as not-null where appropriate, or accept the nullable default, making their intentions clear. This would parallel Kotlin?s philosophy, but in an inverse way: * In Kotlin: all types are not-null by default, nullable types must be explicitly declared. * In Java (with this proposal): all types would be nullable by default, but not-null types would be explicitly declared ? with the added benefit of a warning to help modernize existing code. I know it?s a bit unusual, but I believe this approach could strike a balance between safety, clarity, and backward compatibility. Thank you for your great work on Java! Best regards, Abdurasul Abduraimov -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Thu Jun 12 12:27:23 2025 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 12 Jun 2025 14:27:23 +0200 (CEST) Subject: Suggestion regarding Null State Analysis in Project Valhalla In-Reply-To: References: Message-ID: <1208549467.17783196.1749731243645.JavaMail.zimbra@univ-eiffel.fr> Hello Abdurasul , We know from people that have added annotations (jspecify or others) to big codebases that not having an unspecified state (or as you suggest having an unspecified state with warnings) generates too many warnings to the point developers find it a burden. I think the real answer is we will see once we first have a prototype. regards, R?mi > From: "Brian Goetz" > To: "valhalla-spec-experts" > Sent: Thursday, June 12, 2025 1:55:19 PM > Subject: Fwd: Suggestion regarding Null State Analysis in Project Valhalla > Received on the -comments list. >> Begin forwarded message: >> From: Abdurasul Abduraimov < [ mailto:abdurasulabduraimov22 at gmail.com | >> abdurasulabduraimov22 at gmail.com ] > >> Subject: Suggestion regarding Null State Analysis in Project Valhalla >> Date: June 12, 2025 at 1:06:49 AM EDT >> To: [ mailto:valhalla-spec-comments at openjdk.org | >> valhalla-spec-comments at openjdk.org ] >> Dear Team, >> I am a big fan of Java and I?m eagerly awaiting the release of Project Valhalla. >> I watched the Valhalla session from IntelliJ IDEA Conf 2025 (Day 1), where R?mi >> Forax discussed the "Null State Analysis" feature. As he explained, the system >> defines three null states: >> 1. >> Null-restricted: Integer! or String! >> 2. >> Nullable: Integer? or String? >> 3. >> Unspecified: Integer or String (with no warning) >> I understand that due to Java?s large amount of legacy code, introducing >> nullable and non-nullable types (as in Kotlin) is challenging, and the team is >> prioritizing backward compatibility. >> However, I?d like to propose an idea: >> What if the Unspecified state also emitted a warning? This way, all types would >> continue to be effectively nullable (as they are today), but developers >> upgrading to future Java versions (where Valhalla is finalized) would be >> encouraged to explicitly annotate their types. They could mark types as >> not-null where appropriate, or accept the nullable default, making their >> intentions clear. >> This would parallel Kotlin?s philosophy, but in an inverse way: >> * >> In Kotlin: all types are not-null by default, nullable types must be explicitly >> declared. >> * >> In Java (with this proposal): all types would be nullable by default, but >> not-null types would be explicitly declared ? with the added benefit of a >> warning to help modernize existing code. >> I know it?s a bit unusual, but I believe this approach could strike a balance >> between safety, clarity, and backward compatibility. >> Thank you for your great work on Java! >> Best regards, >> Abdurasul Abduraimov -------------- next part -------------- An HTML attachment was scrubbed... URL: