Skip to content

Build time initialization for substitution class is wrong #2936

Closed
@ziyilin

Description

@ziyilin

Describe the issue
For clarity, I refer the original class to be substituted as target class, and the substitution class annotated with @TargetClass as substitution class.
Current class initialization attempts to initialize the target class at build time, which is unnecessary and causes initialization errors.
Current initialization process firstly initializes all unconfigured classes as safe, and then checks whether the class is safe in method com.oracle.svm.hosted.classinitialization.TypeInitializerGraph.tryPromoteToUnsafe:
image

type.getClassInitializer() here gets the wrapped type's initializer which is actually the substitution class' initializer.
image

However, at last when the method com.oracle.svm.hosted.classinitialization.ClassInitializationFeature.initializeSafeDelayedClasses initializes the safe classes, it initializes the class c which is actually the target class.
image

The problem to initialize a class with substitution is the class under safety checking and initialization are inconsistency. Therefore, if the substitution class is safe but the target class is not, the initialization will lead to build time errors. Actually when the class is substituted with @Substitute or @Delete, the target class will never appear at runtime, and it's not necessary to initialize it at build time at all.

A patch to fix this issue is proposed: #2935

Steps to reproduce the issue
This issue was discovered from a realistic application using log4j, and can be reproduced with the attached simplified test:
testClinit.zip

  1. Unzip testClinit.zip
  2. Edit clinitTest.sh to set GRAALVM_CP to GRAALVM_CP_8 or GRAALVM_CP_11 according to your own environment.
  3. Run clinitTest.sh and it fails with the follows messges:
To see how the classes got initialized, use --trace-class-initialization=org.apache.logging.log4j.util.LoaderUtil,org.apache.logging.log4j.util.PropertiesUtil
[com.alibaba.test.clinittest:77312]        write:     198.52 ms,  2.35 GB
Error: Classes that should be initialized at run time got initialized during image building:
 org.apache.logging.log4j.util.LoaderUtil was unintentionally initialized at build time. To see why org.apache.logging.log4j.util.LoaderUtil got initialized use --trace-class-initialization=org.apache.logging.log4j.util.LoaderUtil
org.apache.logging.log4j.util.PropertiesUtil was unintentionally initialized at build time. To see why org.apache.logging.log4j.util.PropertiesUtil got initialized use --trace-class-initialization=org.apache.logging.log4j.util.PropertiesUtil

com.oracle.svm.core.util.UserError$UserException: Classes that should be initialized at run time got initialized during image building:
 org.apache.logging.log4j.util.LoaderUtil was unintentionally initialized at build time. To see why org.apache.logging.log4j.util.LoaderUtil got initialized use --trace-class-initialization=org.apache.logging.log4j.util.LoaderUtil
org.apache.logging.log4j.util.PropertiesUtil was unintentionally initialized at build time. To see why org.apache.logging.log4j.util.PropertiesUtil got initialized use --trace-class-initialization=org.apache.logging.log4j.util.PropertiesUtil

Describe GraalVM and your environment:

  • GraalVM version: 9d0a251
  • JDK major version: 8 and 11
  • OS: Linux
  • Architecture: [e.g.: AMD64]

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions