Skip to content

Conversation

@slawekjaranowski
Copy link
Member

For bigger and more complicated classes org.objectweb.asm.ClassWriter requires access to classloader where can found classes used in transformed class.

Also add a warning when a class cannot be transformed.

For bigger and more complicated classes org.objectweb.asm.ClassWriter
requires access to classloader where can found classes used in transformed class.

Also add a warning when a class cannot be transformed.
@slawekjaranowski slawekjaranowski self-assigned this May 9, 2025
@slawekjaranowski slawekjaranowski added this to the next-release milestone May 9, 2025
@kriegaex
Copy link
Contributor

kriegaex commented May 10, 2025

Looks good to me, tests fine, but I did not thoroughtly review the code. Just some quick feedback here. BTW, I ran my test with these changes in place, which I also found useful when debugging the issue before, being curious about the root cause. Not sure if you would like to add something like this for debug logging (I am logging on INFO for my private use case, just change it to DEBUG if necessary).

image

block-exit-transformer.patch

[INFO] --- exec:3.5.1-SNAPSHOT:java (convert-xsd-to-rng) @ convert-xsd-to-rnc ---
"anyType" is implicitly used as the content model of this element. Is this your intention? If so, please consider to write it explicitly as type="anyType".
  1088:72@file:///C:/Users/alexa/Documents/java-src/convert-xsd-to-rnc/dbchangelog-4.31.xsd
[INFO] 
[INFO] --- exec:3.5.1-SNAPSHOT:java (convert-liquibase-rng-to-rnc) @ convert-xsd-to-rnc ---
[INFO] com.thaiopensource.relaxng.translate.Driver::main - replacing System.exit() with SystemExitManager.exit()
[INFO] com.sun.msv.datatype.regexp.REUtil::main - replacing System.exit() with SystemExitManager.exit()
[INFO] System::exit was called with return code 0

@kriegaex
Copy link
Contributor

kriegaex commented May 10, 2025

Besides, in order to test that System::exit is also replaced correctly in constructors, static main methods and even static initialisers, I was using this:

public class Foo {
  static {
    System.exit(0);
  }

  public Foo() {
    System.exit(0);
  }

  public static void main(String[] args) {
    System.exit(0);
  }

  public void foo() {
    System.exit(0);
  }
}

As you can see below, those cases are indeed handled correctly, but of course a System.exit(0) causes an ExceptionInInitializerError despite exit code 0 due to the SystemExitException not being handled there. @slawekjaranowski, maybe you have an idea how to handle this corner case more gracefully (nice to have, not must have).

[INFO] --- exec:3.5.1-SNAPSHOT:java (dummy) @ convert-xsd-to-rnc ---
[INFO] Foo::<init> - replacing System.exit() with SystemExitManager.exit()
[INFO] Foo::main - replacing System.exit() with SystemExitManager.exit()
[INFO] Foo::foo - replacing System.exit() with SystemExitManager.exit()
[INFO] Foo::<clinit> - replacing System.exit() with SystemExitManager.exit()
[WARNING] 
java.lang.ExceptionInInitializerError
    at jdk.internal.misc.Unsafe.ensureClassInitialized0 (Native Method)
    at jdk.internal.misc.Unsafe.ensureClassInitialized (Unsafe.java:1166)
    at java.lang.invoke.DirectMethodHandle.checkInitialized (DirectMethodHandle.java:388)
    at java.lang.invoke.DirectMethodHandle.ensureInitialized (DirectMethodHandle.java:376)
    at java.lang.invoke.DirectMethodHandle.internalMemberNameEnsureInit (DirectMethodHandle.java:341)
    at org.codehaus.mojo.exec.ExecJavaMojo.doMain (ExecJavaMojo.java:371)
    at org.codehaus.mojo.exec.ExecJavaMojo.doExec (ExecJavaMojo.java:360)
    at org.codehaus.mojo.exec.ExecJavaMojo.lambda$execute$0 (ExecJavaMojo.java:280)
    at java.lang.Thread.run (Thread.java:1447)
Caused by: org.codehaus.mojo.exec.SystemExitException: System::exit was called with return code 0
    at org.codehaus.mojo.exec.SystemExitManager.exit (SystemExitManager.java:51)
    at Foo.<clinit> (Foo.java:3)
    at jdk.internal.misc.Unsafe.ensureClassInitialized0 (Native Method)
    at jdk.internal.misc.Unsafe.ensureClassInitialized (Unsafe.java:1166)
    at java.lang.invoke.DirectMethodHandle.checkInitialized (DirectMethodHandle.java:388)
    at java.lang.invoke.DirectMethodHandle.ensureInitialized (DirectMethodHandle.java:376)
    at java.lang.invoke.DirectMethodHandle.internalMemberNameEnsureInit (DirectMethodHandle.java:341)
    at org.codehaus.mojo.exec.ExecJavaMojo.doMain (ExecJavaMojo.java:371)
    at org.codehaus.mojo.exec.ExecJavaMojo.doExec (ExecJavaMojo.java:360)
    at org.codehaus.mojo.exec.ExecJavaMojo.lambda$execute$0 (ExecJavaMojo.java:280)
    at java.lang.Thread.run (Thread.java:1447)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------

Please consider adding a class like this to your test bed.

     <execution>
      <id>dummy</id>
      <phase>verify</phase>
      <goals>
       <goal>java</goal>
      </goals>
      <configuration>
       <mainClass>Foo</mainClass>
       <blockSystemExit>true</blockSystemExit>
      </configuration>
     </execution>

@kriegaex
Copy link
Contributor

@slawekjaranowski, maybe like this to handle the ExceptionInInitializerError caused by SystemExitException in the corner case?

image

exec-java-mojo.patch

[INFO] --- exec:3.5.1-SNAPSHOT:java (dummy) @ convert-xsd-to-rnc ---
[INFO] Foo::<init> - replacing System.exit() with SystemExitManager.exit()
[INFO] Foo::main - replacing System.exit() with SystemExitManager.exit()
[INFO] Foo::foo - replacing System.exit() with SystemExitManager.exit()
[INFO] Foo::<clinit> - replacing System.exit() with SystemExitManager.exit()
[INFO] System::exit was called with return code 0

Or, if you use System.exit(1) in the static block:

[INFO] --- exec:3.5.1-SNAPSHOT:java (dummy) @ convert-xsd-to-rnc ---
[INFO] Foo::<init> - replacing System.exit() with SystemExitManager.exit()
[INFO] Foo::main - replacing System.exit() with SystemExitManager.exit()
[INFO] Foo::foo - replacing System.exit() with SystemExitManager.exit()
[INFO] Foo::<clinit> - replacing System.exit() with SystemExitManager.exit()
[ERROR] System::exit was called with return code 1
[WARNING] 
org.codehaus.mojo.exec.SystemExitException: System::exit was called with return code 1
    at org.codehaus.mojo.exec.SystemExitManager.exit (SystemExitManager.java:51)
    at Foo.<clinit> (Foo.java:3)
    at jdk.internal.misc.Unsafe.ensureClassInitialized0 (Native Method)
    at jdk.internal.misc.Unsafe.ensureClassInitialized (Unsafe.java:1166)
    at java.lang.invoke.DirectMethodHandle.checkInitialized (DirectMethodHandle.java:388)
    at java.lang.invoke.DirectMethodHandle.ensureInitialized (DirectMethodHandle.java:376)
    at java.lang.invoke.DirectMethodHandle.internalMemberNameEnsureInit (DirectMethodHandle.java:341)
    at org.codehaus.mojo.exec.ExecJavaMojo.doMain (ExecJavaMojo.java:383)
    at org.codehaus.mojo.exec.ExecJavaMojo.doExec (ExecJavaMojo.java:372)
    at org.codehaus.mojo.exec.ExecJavaMojo.lambda$execute$0 (ExecJavaMojo.java:280)
    at java.lang.Thread.run (Thread.java:1447)

@slawekjaranowski
Copy link
Member Author

@kriegaex thanks for review ...

first proposition - I would like to log in debug level info about replace exit method

second - with next test it is ok for me

@kriegaex
Copy link
Contributor

kriegaex commented May 15, 2025

@slawekjaranowski, so are you taking it from here or waiting for me to do anything else? Something like another PR piggy-backing on top of this one? I am just asking to avoid a stalemate of two people waiting for the other one to move first.

@slawekjaranowski
Copy link
Member Author

@slawekjaranowski, so are you taking it from here or waiting for me to do anything else? Something like another PR piggy-backing on top of this one? I am just asking to avoid a stalemate of two people waiting for the other one to move first.

simply lack of time ....

I will merge it as is, without additional not related changes.

It will be great if you prepare separate PRs with your proposition.

@slawekjaranowski slawekjaranowski merged commit 42bc369 into master May 15, 2025
29 checks passed
@slawekjaranowski slawekjaranowski deleted the class-writer-classloader branch May 15, 2025 18:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants