asm issueshttps://gitlab.ow2.org/asm/asm/-/issues2021-09-19T09:10:54Zhttps://gitlab.ow2.org/asm/asm/-/issues/317952Instruction visitJumpInsn(GOTO,label) with element in stack generate a ERROR2021-09-19T09:10:54ZGabirel XavierInstruction visitJumpInsn(GOTO,label) with element in stack generate a ERRORHi, thanks very mutch for the you work
My name is Gabriel, and i'm writing a university work that is a compile, and i noted that every time i call a jump instruction with GOTO opcode, and has a value in the stack, i got a error "Excepti...Hi, thanks very mutch for the you work
My name is Gabriel, and i'm writing a university work that is a compile, and i noted that every time i call a jump instruction with GOTO opcode, and has a value in the stack, i got a error "Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0".
What is wrong here? Some one can help-me?https://gitlab.ow2.org/asm/asm/-/issues/317955ClassReader fails to parse class file due to InputStream optimization2021-09-19T09:10:46Z180254ClassReader fails to parse class file due to InputStream optimization**Introductory information**
In my project, after switching from using spring framework 5.3.7 to 5.3.10 at the very beginning of start I'm getting following exception:
```
java.lang.IllegalArgumentException: Unsupported class file major...**Introductory information**
In my project, after switching from using spring framework 5.3.7 to 5.3.10 at the very beginning of start I'm getting following exception:
```
java.lang.IllegalArgumentException: Unsupported class file major version 21845
at org.springframework.asm.ClassReader.<init>(ClassReader.java:199)
at org.springframework.asm.ClassReader.<init>(ClassReader.java:180)
at org.springframework.asm.ClassReader.<init>(ClassReader.java:166)
at org.springframework.asm.ClassReader.<init>(ClassReader.java:287)
at org.springframework.core.type.classreading.SimpleMetadataReader.getClassReader(SimpleMetadataReader.java:57)
... 39 common frames omitted
Wrapped by: org.springframework.core.NestedIOException: ASM ClassReader failed to parse class file - probably due to a new Java class file version that isn't supported yet: class path resource [com/example/demo/HealthConfig.class]; nested exception is java.lang.IllegalArgumentException: Unsupported class file major version 21845
at org.springframework.core.type.classreading.SimpleMetadataReader.getClassReader(SimpleMetadataReader.java:60)
at org.springframework.core.type.classreading.SimpleMetadataReader.<init>(SimpleMetadataReader.java:49)
at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:103)
at org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory.createMetadataReader(ConcurrentReferenceCachingMetadataReaderFactory.java:86)
at org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory.getMetadataReader(ConcurrentReferenceCachingMetadataReaderFactory.java:73)
at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:81)
at org.springframework.context.annotation.ConfigurationClassParser.asSourceClass(ConfigurationClassParser.java:696)
at org.springframework.context.annotation.ConfigurationClassParser$SourceClass.getRelated(ConfigurationClassParser.java:1090)
at org.springframework.context.annotation.ConfigurationClassParser$SourceClass.getAnnotationAttributes(ConfigurationClassParser.java:1071)
at org.springframework.context.annotation.ConfigurationClassParser.collectImports(ConfigurationClassParser.java:549)
at org.springframework.context.annotation.ConfigurationClassParser.getImports(ConfigurationClassParser.java:522)
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:311)
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:199)
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:304)
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:207)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:175)
... 22 common frames omitted
```
We reported this issue in the spring-framework project (https://github.com/spring-projects/spring-framework/issues/27429). It turned out that the exception comes from a class that is a fork the asm project.
**The environment in which the problem occurs:**
The environment we use uses the cloudflare's zlib fork (https://github.com/cloudflare/zlib).
As long as uses zlib distributed with a system, everything is fine.
The problem appears when uses the mentioned zlib fork.
**What is the problem:**
Commit which introduces the problematic change is:
https://gitlab.ow2.org/asm/asm/-/commit/cfda364ce57e39412b6cc89699b1003c6da6ec41
In the mentioned environment the last call to `inputStream.read(data, 0, bufferSize))` returns -1, and and despite that the passed data buffer has been modified.
For this reason, the marked if statement in the following code snippet returns invalid data, and consequently the exception shown in the preliminary information.
```
while ((bytesRead = inputStream.read(data, 0, bufferSize)) != -1) {
outputStream.write(data, 0, bytesRead);
readCount++;
}
outputStream.flush();
if (readCount == 1) { // <-------------------
return data;
}
return outputStream.toByteArray();
```
**Reproduction steps:**
I created simple reproduction steps using spring framework.
https://github.com/180254/spring-framework-issue-27429
By running scripts indexed 0, 1 and 2, you can see that the problem occurs after the problematic commit has been made to spring-framework.
By running scripts indexed 3 and 4, you can see proof the the buffer was modified in the last pass of the loop on the environment with cloudflare zlib fork.
**Final words:**
The problem is somewhere between sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream - asm - cloudflare-gzip-fork. In such an environment a InputStream implementation has a very surprising optimization. Despite returning -1, the passed buffer has been modified.
The problem appears on a custom environment. However it seems to me, that cloudflare's zlib fork is so good and popular, that it is worth to take this problem and continue compatibility of spring-boot - asm - cloudflare-zlib-fork.
Please pick up the issue and consider supporting such behavior.https://gitlab.ow2.org/asm/asm/-/issues/317949Documentation lists outdated Opcodes.ASM_X values in javadoc2021-08-22T09:47:52ZraphwDocumentation lists outdated Opcodes.ASM_X values in javadocAt different places, for example `ClassVisitor` ASM lists the allowed values for the `api` field to be *The ASM API version implemented by this visitor. The value of this field must be one of Opcodes.ASM4, Opcodes.ASM5, Opcodes.ASM6 or O...At different places, for example `ClassVisitor` ASM lists the allowed values for the `api` field to be *The ASM API version implemented by this visitor. The value of this field must be one of Opcodes.ASM4, Opcodes.ASM5, Opcodes.ASM6 or Opcodes.ASM7.* This is outdated. Maybe the documentation should just refer to a range defined by `Opcodes` without listing the values.https://gitlab.ow2.org/asm/asm/-/issues/317943CheckClassAdapter visit method does not allow a private or protected inner class2021-06-06T07:07:17ZDavid StevensonCheckClassAdapter visit method does not allow a private or protected inner classIf an inner class is private or protected, CheckClassAdapter visit method throws IllegalArgumentException in checkAccess method.
A suggested change is if the name contains a '$' to add ACC_PROTECTED and ACC_PRIVATE to valid access codes.If an inner class is private or protected, CheckClassAdapter visit method throws IllegalArgumentException in checkAccess method.
A suggested change is if the name contains a '$' to add ACC_PROTECTED and ACC_PRIVATE to valid access codes.https://gitlab.ow2.org/asm/asm/-/issues/317945LdcInsnNode javadoc is outdated2021-06-06T07:03:30ZJanmm14LdcInsnNode javadoc is outdatedjavadoc of constructor does not mention Type
javadoc of cst and constructor do not mention ConstantDynamic
https://asm.ow2.io/javadoc/org/objectweb/asm/tree/LdcInsnNode.htmljavadoc of constructor does not mention Type
javadoc of cst and constructor do not mention ConstantDynamic
https://asm.ow2.io/javadoc/org/objectweb/asm/tree/LdcInsnNode.htmlhttps://gitlab.ow2.org/asm/asm/-/issues/317942[ASM-Util 9.1] ClassCheckAdaptor output represents reference arrays as only t...2021-05-29T08:11:23ZOliver Wendt[ASM-Util 9.1] ClassCheckAdaptor output represents reference arrays as only their "root" component typeWhen using a ClassCheckAdaptor's output, locals and stack objects which are arrays of references are only shown as their "root" component type. That is to say, `[Ljava/lang/String;`, `[[Ljava/lang/String;`, and so on are only shown as `S...When using a ClassCheckAdaptor's output, locals and stack objects which are arrays of references are only shown as their "root" component type. That is to say, `[Ljava/lang/String;`, `[[Ljava/lang/String;`, and so on are only shown as `String`, rather than `[[String` or something along those lines. This does not apply to arrays whose root component type is primitive - for example, `[I`, `[[I`, and so on are output correctly.
Example:
What is shown
```
test([C[[C[Ljava/lang/String;[[Ljava/lang/String;)V
00000 [C [[C String String : : ALOAD 0
00001 [C [[C String String : [C : ALOAD 1
00002 [C [[C String String : [C [[C : ALOAD 2
00003 [C [[C String String : [C [[C String : ALOAD 3
00004 [C [[C String String : [C [[C String String : RETURN
```
What should be shown
```
test([C[[C[Ljava/lang/String;[[Ljava/lang/String;)V
00000 [C [[C [String [[String : : ALOAD 0
00001 [C [[C [String [[String : [C : ALOAD 1
00002 [C [[C [String [[String : [C [[C : ALOAD 2
00003 [C [[C [String [[String : [C [[C [String : ALOAD 3
00004 [C [[C [String [[String : [C [[C [String [[String : RETURN
```https://gitlab.ow2.org/asm/asm/-/issues/317944ClassReader#readStackMapFrame erroneously assumes stack size 1 for SAME_LOCA...2021-05-29T08:10:17ZJan LührClassReader#readStackMapFrame erroneously assumes stack size 1 for SAME_LOCALS_1_STACK_ITEM_FRAMEHey, I'm tracing down a potential bug regarding stack map frames. The issue occurs when scanning Stapler#service https://github.com/stapler/stapler/blob/stapler-parent-1.262/core/src/main/java/org/kohsuke/stapler/Stapler.java#L225-L233. ...Hey, I'm tracing down a potential bug regarding stack map frames. The issue occurs when scanning Stapler#service https://github.com/stapler/stapler/blob/stapler-parent-1.262/core/src/main/java/org/kohsuke/stapler/Stapler.java#L225-L233. Class files are availble at: https://mvnrepository.com/artifact/org.kohsuke.stapler/stapler/1.262
Disassambling the code for the affected lines results in:
```
248: getstatic #88 // Field org/kohsuke/stapler/MetaClass.NO_CACHE:Z
251: ifeq 258
254: lconst_0
255: goto 261
258: ldc2_w #89 // long 86400000l
261: lstore 9
263: iload 6
```
Here, 261 refers to a double-sized word. Before offset 261, asm reports a type 4 stack map frame with stack size 1. This should be one item with size 2. The preceding if-sequence causes a stack-info to be present in the class file. When looking at https://gitlab.ow2.org/asm/asm/-/blob/master/asm/src/main/java/org/objectweb/asm/ClassReader.java#L3250, for type Frame.SAME_LOCALS_1_STACK_ITEM_FRAME the stack size is set to 1.
```java
} else if (frameType < Frame.RESERVED) {
offsetDelta = frameType - Frame.SAME_LOCALS_1_STACK_ITEM_FRAME;
currentOffset =
readVerificationTypeInfo(
currentOffset, context.currentFrameStackTypes, 0, charBuffer, labels);
context.currentFrameType = Opcodes.F_SAME1;
context.currentFrameStackCount = 1;
```
In hotspot however, the stack size is set to 2 whenever a double-size word is encountered:
https://github.com/JetBrains/jdk8u_hotspot/blob/master/src/share/vm/classfile/stackMapTable.cpp#L242
```cpp
if (stack[0].is_category2()) {
stack[1] = stack[0].to_category2_2nd();
stack_size = 2;
}
```
Is this a bug in ASM? I tested versions 8.0.2 and 9.1.https://gitlab.ow2.org/asm/asm/-/issues/317941COMPUTE_FRAMES flag stops ClassFileTransformer from seeing more classes durin...2021-03-31T22:57:48ZZhiqiang ZangCOMPUTE_FRAMES flag stops ClassFileTransformer from seeing more classes during instrumentation with a ternary operatorCOMPUTE_FRAMES flag stops ClassFileTransformer from seeing more classes during instrumentation with a ternary operator.
Here is an example `AbstractVehicle av = isTrue() ? new LandVehicle() : SeaVehicle();` to trigger the issue. None of...COMPUTE_FRAMES flag stops ClassFileTransformer from seeing more classes during instrumentation with a ternary operator.
Here is an example `AbstractVehicle av = isTrue() ? new LandVehicle() : SeaVehicle();` to trigger the issue. None of classfiles of AbstractVehicle, LandVehicle or SeaVehicle is visible to ClassFileTransformer when COMPUTE_FRAMES is used to construct a ClassWriter.
Please extract[compute-frames-bug.zip](/uploads/e9458129698ba220975aba932e4d096f/compute-frames-bug.zip) and run `./run.sh` for a quick replication.https://gitlab.ow2.org/asm/asm/-/issues/317932More details on Frame generation Exceptions / Errors2021-03-13T14:27:36ZAura LeeMore details on Frame generation Exceptions / ErrorsI'm trying to find out why my code throws an AssertionError at org.objectweb.asm.Frame.putAbstractType(Frame.java:1465), but the Error gives no information at all why it even happened. This makes it really hard to find out what is wrong ...I'm trying to find out why my code throws an AssertionError at org.objectweb.asm.Frame.putAbstractType(Frame.java:1465), but the Error gives no information at all why it even happened. This makes it really hard to find out what is wrong with my code (see below).
I was experimenting with try catch blocks and weird flow and got this exception with frame generation:
```
java.lang.AssertionError
at org.objectweb.asm.Frame.putAbstractType(Frame.java:1465)
at org.objectweb.asm.MethodWriter.putAbstractTypes(MethodWriter.java:1959)
at org.objectweb.asm.MethodWriter.putFrame(MethodWriter.java:1943)
at org.objectweb.asm.MethodWriter.visitFrameEnd(MethodWriter.java:1850)
at org.objectweb.asm.Frame.accept(Frame.java:1393)
at org.objectweb.asm.MethodWriter.computeAllFrames(MethodWriter.java:1628)
at org.objectweb.asm.MethodWriter.visitMaxs(MethodWriter.java:1546)
```
This was my code which doesn't work with COMPUTE_FRAMES, but works if i move the `tcbEnd` label before the return instruction. (I thought it doesn't matter to the frames where try catch blocks start and end?)
```java
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
cw.visit(V1_6, ACC_PUBLIC | ACC_SUPER, "WeirdError", null, "java/lang/Object", null);
MethodVisitor mv = cw.visitMethod(ACC_PRIVATE, "test", "(Ljava/lang/Object;)V", null, null);
mv.visitCode();
Label tcbStart = new Label();
Label tcbEnd = new Label();
Label tcbHandler = new Label();
mv.visitTryCatchBlock(tcbStart, tcbEnd, tcbHandler, "java/lang/RuntimeException");
Label startLabel = new Label();
mv.visitLabel(startLabel);
mv.visitInsn(ICONST_1);
Label returnLabel = new Label();
mv.visitJumpInsn(IFEQ, returnLabel);
mv.visitInsn(ACONST_NULL);
mv.visitVarInsn(ASTORE, 2);
mv.visitInsn(ICONST_0);
mv.visitVarInsn(ISTORE, 3);
mv.visitInsn(ICONST_0);
mv.visitVarInsn(ISTORE, 4);
Label startCompare = new Label();
mv.visitLabel(startCompare);
mv.visitVarInsn(ILOAD, 4);
mv.visitVarInsn(ILOAD, 3);
Label label9 = new Label();
mv.visitJumpInsn(IF_ICMPGE, label9);
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(ILOAD, 4);
mv.visitInsn(AALOAD);
mv.visitVarInsn(ASTORE, 8);
Label label10 = new Label();
mv.visitLabel(label10);
mv.visitInsn(ACONST_NULL);
mv.visitLabel(tcbStart);
mv.visitInsn(POP);
mv.visitIincInsn(7, 1);
mv.visitVarInsn(ALOAD, 8);
mv.visitInsn(MONITOREXIT);
mv.visitJumpInsn(GOTO, label10);
mv.visitLabel(label9);
mv.visitJumpInsn(GOTO, startLabel);
mv.visitLabel(returnLabel);
mv.visitInsn(RETURN);
mv.visitLabel(tcbEnd);
mv.visitInsn(ACONST_NULL);
mv.visitInsn(ATHROW);
mv.visitLabel(tcbHandler);
mv.visitInsn(POP);
mv.visitJumpInsn(GOTO, startCompare);
mv.visitMaxs(200, 9);
mv.visitEnd();
cw.visitEnd();
Files.write(new File("WeirdError.class").toPath(), cw.toByteArray());
```
It would be nice to have more information on all thrown Throwables in `Frame.java`. (Or maybe this part of the code should actually not be reached, I don't know)https://gitlab.ow2.org/asm/asm/-/issues/317940Add OpCodes.ASM_LATEST2021-03-13T10:22:37ZKrzysztof KrasonAdd OpCodes.ASM_LATESTSome projects (like maven plugins one, see https://github.com/apache/maven-plugin-tools/pull/32/files) explicitly need to state the supported ASM version and they use e.g. OpCodes.ASM8 to do that.
Because such projects don't upgrade oft...Some projects (like maven plugins one, see https://github.com/apache/maven-plugin-tools/pull/32/files) explicitly need to state the supported ASM version and they use e.g. OpCodes.ASM8 to do that.
Because such projects don't upgrade often there is an issue that one needs to upgrade asm independently of the project that we depend on. And this creates an issue because it is not possible if one uses OpCodes.ASM*.
My suggestion is to create a simple pointer to the latest (non-experimental) version:
e.g.:
OpCodes.ASM_LATEST = OpCodes.ASM9
And maybe:
OpCodes.ASM_EXPERIMENTAL_LATEST = OpCodes.ASM10_EXPERIMENTAL
This way if project uses that *_LATEST alias it can be sure to support the newest possible ASM.https://gitlab.ow2.org/asm/asm/-/issues/317937Way to retrieve methods that failed conversion in ClassWriter2021-03-07T15:56:34ZAura LeeWay to retrieve methods that failed conversion in ClassWriterWhen I write a ClassNode using ClassWriter and it fails on e.g. frame generation, I get a thrown exception, but there is no way to retrieve the method that it failed in. Can you implement a method in ClassWriter that returns the method i...When I write a ClassNode using ClassWriter and it fails on e.g. frame generation, I get a thrown exception, but there is no way to retrieve the method that it failed in. Can you implement a method in ClassWriter that returns the method it last visited?https://gitlab.ow2.org/asm/asm/-/issues/317938Lambda targets are not remapped2021-03-07T15:56:18Zx4eLambda targets are not remappedHi, I have encountered an issue with the remapping of InvokeDynamics, specifically when dealing with Javac compiled invokedynamics.
To explain I made a simple example:
```java
import org.objectweb.asm.*;
import org.objectweb.asm.commons...Hi, I have encountered an issue with the remapping of InvokeDynamics, specifically when dealing with Javac compiled invokedynamics.
To explain I made a simple example:
```java
import org.objectweb.asm.*;
import org.objectweb.asm.commons.*;
import org.objectweb.asm.tree.*;
import org.objectweb.asm.util.*;
import java.io.PrintWriter;
public class Test {
public static void main(String[] args) throws Throwable {
ClassNode classNode = new ClassNode();
new ClassReader("Example").accept(classNode, ClassReader.SKIP_DEBUG);
print(classNode);
ClassNode newNode = new ClassNode();
Remapper remapper = new SimpleRemapper(
"Example.something()V",
"different"
);
classNode.accept(new ClassRemapper(newNode, remapper));
print(newNode);
}
public static void print(ClassNode cn) {
Textifier textifier = new Textifier();
PrintWriter writer = new PrintWriter(System.out, true);
TraceClassVisitor traceClassVisitor = new TraceClassVisitor(null, textifier, writer);
cn.accept(traceClassVisitor);
}
}
interface Example {
static void test() {
((Example) () -> System.out.println("Hello, World!")).something();
}
void something();
}
```
`Example` is a functional interface with the method `something`. A method implements the functional interface and the method `something` as a lambda.
`Test` attempts to remap the name of `something` to `nothing`. The expected behaviour would be for the method's name to change and all references to be updated.
By printing the class before and after the remapper is applied to it we can however see that this is not the case.
Before remapping:
```java
// class version 52.0 (52)
// access flags 0x600
abstract interface Example {
// access flags 0x19
public final static INNERCLASS java/lang/invoke/MethodHandles$Lookup java/lang/invoke/MethodHandles Lookup
// access flags 0x9
public static test()V
INVOKEDYNAMIC something()LExample; [
// handle kind 0x6 : INVOKESTATIC
java/lang/invoke/LambdaMetafactory.metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
// arguments:
()V,
// handle kind 0x6 : INVOKESTATIC
Example.lambda$test$0()V itf,
()V
]
INVOKEINTERFACE Example.something ()V (itf)
RETURN
MAXSTACK = 1
MAXLOCALS = 0
// access flags 0x401
public abstract something()V
// access flags 0x100A
private static synthetic lambda$test$0()V
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "Hello, World!"
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
RETURN
MAXSTACK = 2
MAXLOCALS = 0
}
```
After remapping:
```java
// class version 52.0 (52)
// access flags 0x600
abstract interface Example {
// access flags 0x19
public final static INNERCLASS java/lang/invoke/MethodHandles$Lookup java/lang/invoke/MethodHandles Lookup
// access flags 0x9
public static test()V
INVOKEDYNAMIC something()LExample; [
// handle kind 0x6 : INVOKESTATIC
java/lang/invoke/LambdaMetafactory.metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
// arguments:
()V,
// handle kind 0x6 : INVOKESTATIC
Example.lambda$test$0()V itf,
()V
]
INVOKEINTERFACE Example.different ()V (itf)
RETURN
MAXSTACK = 1
MAXLOCALS = 0
// access flags 0x401
public abstract different()V
// access flags 0x100A
private static synthetic lambda$test$0()V
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "Hello, World!"
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
RETURN
MAXSTACK = 2
MAXLOCALS = 0
}
```
As you can see the arguments of the invokedynamic instruction have not been remapped, it remains as `something()LExample;` which will result in a runtime error.
This can be fixed by providing special behaviour when remapping LambdaMetafactory invokedynamics and there is a patch implementing this here: [https://github.com/MinecraftForge/MinecraftForge/pull/3532](https://github.com/MinecraftForge/MinecraftForge/pull/3532).
Thank Youhttps://gitlab.ow2.org/asm/asm/-/issues/317935Add an option to automatically split methods that exceed the 64k limit2021-03-07T15:52:37ZByteZAdd an option to automatically split methods that exceed the 64k limitI know the ``MethodTooLargeException`` exists because the JVM has a 64k limit. But a util or a ClassWriter option to automatically split methods like these would be extremely useful. Community members have already provided [solutions](ht...I know the ``MethodTooLargeException`` exists because the JVM has a 64k limit. But a util or a ClassWriter option to automatically split methods like these would be extremely useful. Community members have already provided [solutions](https://github.com/cretz/msplit) for this issue, but they're mostly outdated and don't work anymore.https://gitlab.ow2.org/asm/asm/-/issues/317939ASM RecordComponentVisitor does not visit component annotations2021-03-07T15:50:39ZChris RankinASM RecordComponentVisitor does not visit component annotationsI created this example using the "record preview" support in OpenJDK15:
```java
package org.testing;
public record ExampleRecord(
String name,
@MyAnnotation int number,
long bigNumber
) {
public String getMessage() {
...I created this example using the "record preview" support in OpenJDK15:
```java
package org.testing;
public record ExampleRecord(
String name,
@MyAnnotation int number,
long bigNumber
) {
public String getMessage() {
return String.format("name:[%s], number:[%d]. bigNumber:[%ld]", name, number, bigNumber);
}
}
```
When I fed this class into ASM 9.1, the `RecordComponentVisitor` did not visit the `number` component's annotation. However, the annotation was visited by the component's `FieldVisitor`.
Have I completely misunderstood how to use a `RecordComponentVisitor` please? But if so, what other "record component annotations" are there to visit?
Thanks,
Chrishttps://gitlab.ow2.org/asm/asm/-/issues/317936Please release a new version2021-02-07T11:57:25ZMatthias KurzPlease release a new versionIt's been a while since the last ASM release.
Can someone please give feedback when a new release is planned?
Thanks!It's been a while since the last ASM release.
Can someone please give feedback when a new release is planned?
Thanks!https://gitlab.ow2.org/asm/asm/-/issues/317933AbstractInsnNode subclasses missing equals2021-01-31T15:14:55ZRamid KhanAbstractInsnNode subclasses missing equals`AbstractInsnNode` and it's subclasses don't extend `equals` nor `hashCode`, which makes it very hard to compare two methods and check if they are equal. We currently have to use [a huge if/else block](https://github.com/Astrarre/Amalgam...`AbstractInsnNode` and it's subclasses don't extend `equals` nor `hashCode`, which makes it very hard to compare two methods and check if they are equal. We currently have to use [a huge if/else block](https://github.com/Astrarre/Amalgamation/blob/b44215f5340912814efe9bcbb7b2c5c278b66ade/subprojects/platform/src/main/java/io/github/f2bb/amalgamation/platform/merger/impl/method/MethodKey.java#L53-L108), but it would be much easier to maintain if the nodes themselves actually implemented them. Is there a reason for no implementation?https://gitlab.ow2.org/asm/asm/-/issues/317934converting MethodVisitor.visitVarInsn(int opCode, int var) into NOOP?2021-01-28T18:51:33ZGabor Liptakconverting MethodVisitor.visitVarInsn(int opCode, int var) into NOOP?I might have missed pointers in the documentation. What would need to be placed into the `super.visitVarInsn(opCode, var)` call to make the current instruction a NOOP? Using `POP` fails with `java.lang.VerifyError` which is probably expe...I might have missed pointers in the documentation. What would need to be placed into the `super.visitVarInsn(opCode, var)` call to make the current instruction a NOOP? Using `POP` fails with `java.lang.VerifyError` which is probably expected as `POP` doesn't take an argument.https://gitlab.ow2.org/asm/asm/-/issues/317929ClassRemapper doesn't remap annotation values2021-01-28T18:39:17ZAura LeeClassRemapper doesn't remap annotation valuesI am remapping method names using a custom remapper class like this:
```java
ClassNode updated = new ClassNode();
node.accept(new ClassRemapper(updated, new MyRemapper(...)));
```
`MyRemapper` overrides `mapMethodName` and therefore ...I am remapping method names using a custom remapper class like this:
```java
ClassNode updated = new ClassNode();
node.accept(new ClassRemapper(updated, new MyRemapper(...)));
```
`MyRemapper` overrides `mapMethodName` and therefore should update all references to a certain method. My sample class which is run through the `ClassRemapper`:
```java
public class AnnotationRemapTest {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public static @interface Description {
String desc() default "an unknown method";
}
@Description(desc = "the entry point method")
public static void main(String[] args) throws Exception {
Description d = (Description) AnnotationRemapTest.class.getDeclaredMethod("main", String[].class).getAnnotations()[0];
System.out.println("this method is: " + d.desc());
}
}
```
Everything works great, except that `@Description(desc = "the entry point method")` is not updated. In my eyes it is missing a call to mapMethodName to update the annotation value name, which corresponds to its method name inside the annotation class.
Output after remapping:
```java
public class AnnotationRemapTest {
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.METHOD })
public static @interface A {
public String n() default "an unknown method";
}
@A(desc = "the entry point method") // "desc" is left as "desc", while it should be updated to "n"
public static void main(String[] args) throws Exception {
A d = (A) AnnotationRemapTest.class.getDeclaredMethod("main", String[].class).getAnnotations()[0];
System.out.println("this method is: " + d.n());
}
}
```
In short: `AnnotationRemapper` is missing calls to `mapMethodName` to update annotation value names.https://gitlab.ow2.org/asm/asm/-/issues/317930Can CheckClassAdapter.checkTypeRef throw a more specific exception?2021-01-27T18:32:23ZHao ZhongCan CheckClassAdapter.checkTypeRef throw a more specific exception?This method throws AssertionError for unsurpported typeRef:
`static void checkTypeRef(final int typeRef) {
int mask = 0;
switch (typeRef >>> 24) {
case TypeReference.CLASS_TYPE_PARAMETER:
case TypeReference.METHOD_TY...This method throws AssertionError for unsurpported typeRef:
`static void checkTypeRef(final int typeRef) {
int mask = 0;
switch (typeRef >>> 24) {
case TypeReference.CLASS_TYPE_PARAMETER:
case TypeReference.METHOD_TYPE_PARAMETER:
...
default:
throw new AssertionError();
}
if ((typeRef & ~mask) != 0) {
throw new IllegalArgumentException(
"Invalid type reference 0x" + Integer.toHexString(typeRef));
}
}
`
AssertionError is a general exception and it is not quite meaningful. Is it better to throw UnsupportedOperationException? Or else, it shall be consistent, if it throws IllegalArgumentException, as the follow-up lines do.https://gitlab.ow2.org/asm/asm/-/issues/317931Shall CheckMethodAdapter.Method.visitLabel throw IllegalStateException?2021-01-27T18:27:58ZHao ZhongShall CheckMethodAdapter.Method.visitLabel throw IllegalStateException?I notice that this method throws IllegalArgumentException:
` public void visitLabel(final Label label) {
checkVisitCodeCalled();
checkVisitMaxsNotCalled();
checkLabel(label, false, "label");
if (labelInsnIndices.get(labe...I notice that this method throws IllegalArgumentException:
` public void visitLabel(final Label label) {
checkVisitCodeCalled();
checkVisitMaxsNotCalled();
checkLabel(label, false, "label");
if (labelInsnIndices.get(label) != null) {
throw new IllegalArgumentException("Already visited label");
}
labelInsnIndices.put(label, insnCount);
super.visitLabel(label);
}
`
IllegalArgumentException shall be thrown from checkLabel. After calling checkLabel, the format of the label shall be correct, and shall not be considered illegal. The message of the thrown IllegalArgumentException is "Already visited label". It also indicates that the format is correct, but the state does not allow visiting a visisted label again.