asm issueshttps://gitlab.ow2.org/asm/asm/-/issues2017-12-26T10:31:57Zhttps://gitlab.ow2.org/asm/asm/-/issues/316320Quick evaluation of some obvious cases in ClassWriter.getCommonSuperClass2017-12-26T10:31:57ZdjencksQuick evaluation of some obvious cases in ClassWriter.getCommonSuperClass```
Apache Aries needs to override ClassWriter.getCommonSuperClass to use
osgi-friendly class "loading"(using ClassReaders) rather than the default. We
need some obvious special case short-circuit evaluations that are generally
applicab...```
Apache Aries needs to override ClassWriter.getCommonSuperClass to use
osgi-friendly class "loading"(using ClassReaders) rather than the default. We
need some obvious special case short-circuit evaluations that are generally
applicable but no longer as easy to implemnt by overriding without duplicating
information. Perhaps these special-case evaluations could be included in
ClassWriter itself, speeding up the method and simplifying the task of
overriding getCommonSuperClass.
The special cases are:
types are equal
one type is java/lang/Object (so the common superclass must be too)
one type is the class being written, in which case we can move directly to the
known superclass.
This proposed change makes the
ClassWriterUnitTest.testIllegalGetCommonSuperClassArguments less meaningful,
but I fail to see much point in the test anyway.
The superclass name must be in the constant pool somewhere, but I don't
immediately see how to find it, so I added a String field to hold it.
```https://gitlab.ow2.org/asm/asm/-/issues/316319Explicit exception types for 'code size' related exceptions2017-12-26T10:32:09ZpdevaExplicit exception types for 'code size' related exceptions```
Currently the ClassWriter and MethodWriter classes throw runtime exceptions if
the constant pool or code size is too large.
These exceptions are plain RuntimeExceptions with no explicit type.
This is a problem for those who actuall...```
Currently the ClassWriter and MethodWriter classes throw runtime exceptions if
the constant pool or code size is too large.
These exceptions are plain RuntimeExceptions with no explicit type.
This is a problem for those who actually want to catch these exceptions and do
something about them.
For example, we currently de-instrument the method if after instrumentation the
code size is > the 64k limit.
Currently the only way to identify these exceptions is to write a generic
RuntimeException handler and look for the exact message string of the
exception.
This is very type unsafe and frankly an ugly way of writing the handlers.
I propose adding explicitly typed Exceptions for both these cases. The
exceptions still subclass RuntimeException so they are not checked exceptions
and dont change existing callers of these methods.
The changes are described below:
MethodWriter.getSize()
line 1850: throw new RuntimeException("Method code too large!");
should be: throw new MethodSizeException("Method code too large!");
ClassWriter.toByteArray()
line 773: throw new RuntimeException("Class file too large!");
should be: throw new ConstantPoolSizeException("Method code too large!");
New exception classes:
public abstract class SizeException extends RuntimeException {
public SizeException(String message) {
super(message);
}
}
public class MethodSizeException extends SizeException {
public MethodSizeException(String message) {
super(message);
}
}
public class ConstantPoolSizeException extends SizeException {
public ConstantPoolSizeException(String message) {
super(message);
}
}
```https://gitlab.ow2.org/asm/asm/-/issues/316318Allow generated SVUID field to be marked synthetic2017-11-30T14:43:15ZdjencksAllow generated SVUID field to be marked synthetic```
Apache Aries proxies need to be able to mark generated svuid fields as
synthetic. I think this might generally be a useful feature and is easier to
add to the SerialVersionUIDAdder than to add on with delegation/subclassing.
If you...```
Apache Aries proxies need to be able to mark generated svuid fields as
synthetic. I think this might generally be a useful feature and is easier to
add to the SerialVersionUIDAdder than to add on with delegation/subclassing.
If you don't like this idea can you at least add a getter for the hasSVUID
field (it was protected in asm 3, thus accessible to subclasses).
The attached patch adds the optional capability to mark added SerialVersionUID
fields synthetic and enhances the test to check whether the SerialVersionUID
field is actually added when expected and if the added field is synthetic as
configured.
```https://gitlab.ow2.org/asm/asm/-/issues/316306More efficient patch for Frame.merge()2017-12-26T10:32:49ZpdevaMore efficient patch for Frame.merge()```
The Frame.merge(Frame<? extends V> frame, final Interpreter<V> interpreter)
method has a line in its for loop:
changes |= true;
This can be changed to :
changes = true;
since the OR operation will always return true when OR'd w...```
The Frame.merge(Frame<? extends V> frame, final Interpreter<V> interpreter)
method has a line in its for loop:
changes |= true;
This can be changed to :
changes = true;
since the OR operation will always return true when OR'd with 'true'.
Here is the full method with the patched line:
public boolean merge(final Frame<? extends V> frame, final Interpreter<V>
interpreter)
throws AnalyzerException
{
if (top != frame.top) {
throw new AnalyzerException(null, "Incompatible stack heights");
}
boolean changes = false;
for (int i = 0; i < locals + top; ++i) {
V v = interpreter.merge(values[i], frame.values[i]);
if (v != values[i]) {
values[i] = v;
changes == true;
}
}
return changes;
}
```https://gitlab.ow2.org/asm/asm/-/issues/316305Class Writer should thrown exception if method size is greater than 64kb limit2017-12-26T10:33:06ZpdevaClass Writer should thrown exception if method size is greater than 64kb limit```
The ClassWriter.toByteArray() method should throw an exception if it sees that
the method size of any method is greater than the 64k limit of the jvm.
Here is a proposed modification to that method:
while (mb != null)
{
++nbMetho...```
The ClassWriter.toByteArray() method should throw an exception if it sees that
the method size of any method is greater than the 64k limit of the jvm.
Here is a proposed modification to that method:
while (mb != null)
{
++nbMethods;
int methodSize = mb.getSize();
if (methodSize > 65535 )
{
throw new MethodSizeTooLargeException("<info about method");
}
size += methodSize;
mb = (MethodWriter) mb.mv;
}
class MethodSizeTooLargeException extends RuntimeException{
public MethodSizeTooLargeException(String msg){
super(msg);
}
}
```https://gitlab.ow2.org/asm/asm/-/issues/316296Local variable end label in wrong position after ClassReader2017-12-26T10:33:34ZttonelliLocal variable end label in wrong position after ClassReader```
Hi,
I am not sure if this is a bug or if I am misinterpreting some documentation.
When using the ClassReader to read some bytecode (from a class file that I am
sending in attachment) I get the end label of a local variable debug inf...```
Hi,
I am not sure if this is a bug or if I am misinterpreting some documentation.
When using the ClassReader to read some bytecode (from a class file that I am
sending in attachment) I get the end label of a local variable debug info in
the wrong position.
I use the following code for printing the one of its methods (with ASM 4.0):
ClassNode node = new ClassNode();
new ClassReader(new FileInputStream("NestedTryBlocks.class")).accept(node,
ClassReader.SKIP_FRAMES);
MethodNode m = node.methods.get(1);
Printer p = new Textifier();
TraceMethodVisitor v = new TraceMethodVisitor(p);
m.accept(v);
System.out.println(p.getText());
The problem lies in the label for the following variable:
...
, L10
, LINENUMBER 15 L10
, ALOAD 0
, BIPUSH 7
, PUTFIELD NestedTryBlocks.i : I
, L9
, LINENUMBER 17 L9
, ALOAD 0
, ALOAD 0
...
LOCALVARIABLE e1 Ljava/lang/Exception; L10 L9 2
I think that L9 should be between the last "ALOAD 0". If I use javap -p -v on
the same class, I get:
...
17: aload_0
18: bipush 7
20: putfield #22; //Field i:I
23: aload_0
24: aload_0
...
LocalVariableTable:
Start Length Slot Name Signature
...
17 6 2 e1 Ljava/lang/Exception;
According to the JVM spec (
http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#5956
), variable e1 should be defined between instructions at indices 17 and 23
(because it's 17 + 6 and the spec says that the end index is "inclusive").
Now, ASM documentation says that the end label is "exclusive" (see the
description of "end" in
http://asm.ow2.org/asm40/javadoc/user/org/objectweb/asm/tree/LocalVariableNode.html
), so this means that e1 is not defined at instruction 23.
It seems to me that the label for line number is interfering with the local
variable label.
Is this a bug, an optimization (because instruction 23 does not use e1) or am I
misinterpreting something?
Best regards,
Thiago
ps 1 - I tried using SKIP_DEBUG. The label remains there, but also in the wrong
place.
ps 2 - this class is part of the test classes for the quilt project (
http://sourceforge.net/projects/quilt/ )
```https://gitlab.ow2.org/asm/asm/-/issues/316288Deploy ASM 4.0 to Maven central2017-12-26T10:33:47ZseweDeploy ASM 4.0 to Maven central```
Although ASM 4.0 has been released quite some time ago, the latest release
available from the central Maven repository is still ASM 3.3.1.
``````
Although ASM 4.0 has been released quite some time ago, the latest release
available from the central Maven repository is still ASM 3.3.1.
```https://gitlab.ow2.org/asm/asm/-/issues/316212org.objectweb.asm.optimizer.ClassOptimizer does not work with classes in defa...2017-12-12T06:25:41Zpicpromusicorg.objectweb.asm.optimizer.ClassOptimizer does not work with classes in default package```
The line
pkgName = name.substring(0, name.lastIndexOf('/'));
in ClassOptimizer.visit(...) causes an StringArrayOutOfBoundsException when a
class of the default package is passed to the org.objectweb.asm.optimizer.Shrinker.
...```
The line
pkgName = name.substring(0, name.lastIndexOf('/'));
in ClassOptimizer.visit(...) causes an StringArrayOutOfBoundsException when a
class of the default package is passed to the org.objectweb.asm.optimizer.Shrinker.
```https://gitlab.ow2.org/asm/asm/-/issues/316204Analyzer produces incorrect lvt types for jsr return targets when jsr frame c...2017-12-26T09:12:31ZkhoffmanAnalyzer produces incorrect lvt types for jsr return targets when jsr frame changes twice during analysis```
I'm using ASM to perform some analyses that are very sensitive to type
information in the local variable table. Tracking down a problem with the
results of one of the analyses led me to find a rare bug in ASM.
The bug happens when r...```
I'm using ASM to perform some analyses that are very sensitive to type
information in the local variable table. Tracking down a problem with the
results of one of the analyses led me to find a rare bug in ASM.
The bug happens when running BasicInterpreter (and thus Analyzer) on the class
org.eclipse.core.runtime.internal.adaptor.BundleStopper. The problem happens
when you have a JSR instruction that can be reached from two different control
flow paths, one path with more active LVT variables than the other path.
Consider the following (a simplification of the problematic code from
BundleStopper.basicStopBundles()):
for (...) {
try {
Object o1 = new Object();
} catch (Exception e) {
Object o1 = new Object();
Object o2 = new Object();
Object o3 = new Object();
} finally {
System.out.println("hi");
}
}
This gets compiled such that the end of the try block and the end of the catch
block both JUMP to a label and then immediately executes a JSR to the finally
block (the compiler also could have put a separate JSR at the end of each
block, which would have avoided the bug, but for whatever reason, it chose to
JUMP at the end of each block and then do the JSR).
Now consider what happens if Analyzer happens to process the catch block in the
queue before the try block. The catch block uses more LVT slots, and so when it
JUMPs to the label right before the JSR, initially that label will be populated
with type information for all of those LVT slots.
Then let's say that the JSR subroutine happens to be processed next in the
queue. At the end of the JSR when it reaches the RET instruction, it will merge
its current frame at the end of the JSR (except for variables accessed in the
JSR) with the frame of the calling instruction and merge that with the return
target (the instruction following the JSR instruction). At this point the
calling JSR instruction still have a state with the extra LVT variables, and so
it propagates this to the next instruction (the return target, happens to be a
label).
Eventually the queue contains the if block and at the end of the if block we
merge our LVT state with the JUMP target, which reduces the number of valid LVT
slots at the JSR instruction. The JSR instruction gets processed again, but
there are no changes to be merged (the subroutine by this point already had the
LVT slots that were fewer), and so the analysis terminates.
However, this leaves the return target of the JSR instruction (the instruction
after the JSR instruction) with an LVT that has too be many variables in it.
The key insight to fixing this is to realize that anytime the LVT of a JSR
instruction changes, we must add to the queue the RET instructions of the
relevant subroutine.
I have implemented this in the attached patch, and verified that it works
correctly. The patch uses a map to track the RET instruction(s) that jump to
any JSR return target that have already been processed. When a JSR is processed
in the queue, it always adds these RET instructions into the queue as well
(even if no changes were caused by the JSR instruction itself, if we are
processing the JSR instruction something caused the JSR instruction's state
itself to change, so we just propagate this one step further).
I will be attaching the printout of the LVT/STACK of the actual
BundleStopper.basicStopBundles method anaylsis before the fix and after the
fix, as well as the patch against SVN /tags/ASM_3_3_2 release. I'm also
attaching the .jar file with the .class file that will reproduce the problem.
I also fixed another problem along the way with this patch -- if there are
multiple callers for the same subroutine then the code to add another caller to
the subroutine doesn't update all of the copies of the subroutine in the
subroutines array (because findSubroutine makes a deep copy of the subroutine
for each entry). The fix is to update all of the subroutines entries when a
second caller is added to a subroutine object.
```https://gitlab.ow2.org/asm/asm/-/issues/316188ASM fails to load a class file with ClassCircularityError2017-12-26T09:14:58ZjamesssssASM fails to load a class file with ClassCircularityError```
If you have a class that implements an interface and has a method that assign
itself to a variable of type the interface, ASM fails to load the class with a
ClassCircularityError
Occurs with ASM 3.3.1 and JDK 1.6
``````
If you have a class that implements an interface and has a method that assign
itself to a variable of type the interface, ASM fails to load the class with a
ClassCircularityError
Occurs with ASM 3.3.1 and JDK 1.6
```https://gitlab.ow2.org/asm/asm/-/issues/316181ASM throws ArrayIndexOutOfBoundsException while parsing class file2017-12-26T10:35:50Zm_holzhaASM throws ArrayIndexOutOfBoundsException while parsing class file```
Hi,
when reading the attached class file with the following simple commands, ASM
3.3.1 throws an ArrayIndexOutOfBoundsException:
InputStream inputStream = new BufferedInputStream(new
FileInputStream("LittleExamples.class"));
Cl...```
Hi,
when reading the attached class file with the following simple commands, ASM
3.3.1 throws an ArrayIndexOutOfBoundsException:
InputStream inputStream = new BufferedInputStream(new
FileInputStream("LittleExamples.class"));
ClassReader reader = new ClassReader(inputStream);
ClassNode node = new ClassNode();
reader.accept(node, 0);
```https://gitlab.ow2.org/asm/asm/-/issues/316050Invalid conversion of non-BMP characters to UTF82017-12-26T10:36:06ZmhkayInvalid conversion of non-BMP characters to UTF8```
When a string containing non-BMP characters is written to the constant pool, the
conversion to UTF-8 is done incorrectly, resulting in a failure to load the
generated class (ClassFormatError: Illegal UTF-8 string in constant pool)....```
When a string containing non-BMP characters is written to the constant pool, the
conversion to UTF-8 is done incorrectly, resulting in a failure to load the
generated class (ClassFormatError: Illegal UTF-8 string in constant pool).
The method ByteVector.putUTF8() makes no attempt to recognize surrogate pairs in
the supplied string, but instead converts each of the two surrogates separately.
To quote from the Unicode FAQ (http://unicode.org/faq/utf_bom.html#utf8-4),
"The definition of UTF-8 requires that supplementary characters (those using
surrogate pairs in UTF-16) be encoded with a single four byte sequence. However,
there is a widespread practice of generating pairs of three byte sequences in
older software, especially software which pre-dates the introduction of UTF-16
or that is interoperating with UTF-16 environments under particular constraints.
Such an encoding is not conformant to UTF-8 as defined."
```https://gitlab.ow2.org/asm/asm/-/issues/316048ClassFormatError: Illegal exception table range when generating class2017-12-26T10:36:34ZianjoClassFormatError: Illegal exception table range when generating class```
In the middle of doing a complex transformation of a class, I actually end up
with no code between two labels, which are used in a TryCatchBlock (so the
block goes unused).
The ClassWriter correctly detects the TryCatchBlock is empt...```
In the middle of doing a complex transformation of a class, I actually end up
with no code between two labels, which are used in a TryCatchBlock (so the
block goes unused).
The ClassWriter correctly detects the TryCatchBlock is empty and replaces with
the NOP/ATHROW stuff, but it does not remove the entry from the exception
table, resulting in an error when the class is loaded by Java.
The following example demonstrates this:
import java.io.*;
import org.objectweb.asm.*;
public class AsmTryCatchBlockTestcase implements Opcodes {
public static void main(String[] args) throws Exception {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
cw.visit(V1_6, ACC_PUBLIC, "TryCatchIssue", null, "java/lang/Object", null);
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC|ACC_STATIC, "m", "()V", null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
Label l1 = new Label();
mv.visitLabel(l1);
mv.visitInsn(RETURN);
Label l2 = new Label();
mv.visitLabel(l2);
mv.visitInsn(RETURN);
mv.visitTryCatchBlock(l0, l1, l2, null);
mv.visitMaxs(0, 0);
mv.visitEnd();
cw.visitEnd();
FileOutputStream fos = new FileOutputStream("TryCatchIssue.class");
fos.write(cw.toByteArray());
fos.close();
}
}
java TryCatchIssue then results in
$ java TryCatchIssue
Exception in thread "main" java.lang.ClassFormatError: Illegal exception table
range in class file TryCatchIssue
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
Could not find the main class: TryCatchIssue. Program will exit.
I do know that I can fix this (and indeed I do it) in my code by re-processing
the class to fix the exception table, but I believe that this would more
correctly be done inside ClassWriter, when the block is detected to be
unreachable code.
Thanks.
```https://gitlab.ow2.org/asm/asm/-/issues/316027ClassReader leaks file descriptors2017-12-26T10:36:54ZysibataClassReader leaks file descriptors```
ClassReader class in the org.objectweb.asm package doesn't close input streams.
/**
* Constructs a new {@link ClassReader} object.
*
* @param name the binary qualified name of the class to be read.
* @throws ...```
ClassReader class in the org.objectweb.asm package doesn't close input streams.
/**
* Constructs a new {@link ClassReader} object.
*
* @param name the binary qualified name of the class to be read.
* @throws IOException if an exception occurs during reading.
*/
public ClassReader(final String name) throws IOException {
this(ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
+ ".class"));
}
If you use this constructor, any InputStream returned by
ClassLoader.getSystemResourceAsStream() will never be closed properly.
Eventually we will run out of file descriptors on the system.
Regards,
Yoshiki Shibata
```https://gitlab.ow2.org/asm/asm/-/issues/316005Constant pool access2017-11-30T14:43:15ZpfichtnerConstant pool access```
Is there a prefered way to read the entries in the constant pool? I could not
find one.
In the class ClassReader all necessary data is available but it's not accesible
(items are available via #getItem but #getItemCount is missing, ...```
Is there a prefered way to read the entries in the constant pool? I could not
find one.
In the class ClassReader all necessary data is available but it's not accesible
(items are available via #getItem but #getItemCount is missing, field
#maxStringLength is private). To be able to read the data I would need at least
access via getter to this two attributes:
public int getItemCount() {
return items.length;
}
public int getMaxStringLength() {
return maxStringLength;
}
Since both methods do not allow to change attributes' values there is no risk
for adding this methods. On the other side the internal byte[] b is public
mutatable so there would be no increased risk to change items and
maxStringLength to public, too.
Regards Peter
```https://gitlab.ow2.org/asm/asm/-/issues/315984asm-xml.dtd fails to mention FREM element2017-12-26T09:15:34Zseweasm-xml.dtd fails to mention FREM element```
This bug is related to #315942. The DTD and the code are out-of-sync.
``````
This bug is related to #315942. The DTD and the code are out-of-sync.
```https://gitlab.ow2.org/asm/asm/-/issues/315942asm-xml.dtd fails to mention SWAP element2017-12-26T10:37:19Zseweasm-xml.dtd fails to mention SWAP element```
Although the <SWAP> element is generated by
org.objectweb.asm.xml.SAXCodeAdapter.visitInsn, the corresponding DTD fails to
mention this fact.
``````
Although the <SWAP> element is generated by
org.objectweb.asm.xml.SAXCodeAdapter.visitInsn, the corresponding DTD fails to
mention this fact.
```https://gitlab.ow2.org/asm/asm/-/issues/315882java.lang.ClassFormatError: Invalid this class index 4099 in constant pool in...2017-12-26T10:37:52Zxpoinsardjava.lang.ClassFormatError: Invalid this class index 4099 in constant pool in class file```
I am trying to generate a big class with many String constants.
It seems that something went wrong with the constant pool.
I joined the output of the TraceClassVisitor and the generated bytecode.
``````
I am trying to generate a big class with many String constants.
It seems that something went wrong with the constant pool.
I joined the output of the TraceClassVisitor and the generated bytecode.
```https://gitlab.ow2.org/asm/asm/-/issues/315864byte code transformation corrupts classes2017-12-26T10:38:34Zfdabyte code transformation corrupts classes```
Hello,
working with the ASM library I bumped into strange issue, the trivial
transformation might corrupt classes:
ClassReader cr = new ClassReader(buffer);
ClassWriter cw = new ClassWriter(cr, ClassWriter.C...```
Hello,
working with the ASM library I bumped into strange issue, the trivial
transformation might corrupt classes:
ClassReader cr = new ClassReader(buffer);
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
cr.accept(cw, 0);
byte[] res = cw.toByteArray();
a stack size in particular, that causes VerifyError.
I minimized the test as possible. The steps below allows to reproduce the error.
----- Trans.java - code to perform class transformation ------
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
public class Trans {
public static void main(String[] args) {
String s = args[0];
try {
FileInputStream fis = new FileInputStream(s);
int size = fis.available();
byte[] buffer = new byte[size];
fis.read(buffer);
ClassReader cr = new ClassReader(buffer);
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
cr.accept(cw, 0);
byte[] res = cw.toByteArray();
FileOutputStream fos = new FileOutputStream(s + ".i");
fos.write(res);
fos.flush();
fos.close();
System.out.println("Created: " + s + ".i");
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
----- HelloWorld.java - subject of transformation ----
public class HelloWorld {
public static void main(String args[]) {
System.out.println("Hello world");
}
public void meth1() throws MyException {
}
public void meth2() {
try {
meth1();
} catch (MyException re) {
}
}
public void meth3() throws MyException {
try {
} finally {
}
}
static class MyException extends Exception {
}
}
------------------
Steps to reproduce:
# cp ../asm-3.3.1.jar .
# javac -cp asm-3.3.1.jar Trans.java
# javac HelloWorld.java
# java -cp .:asm-3.3.1.jar Trans HelloWorld.class
Created: HelloWorld.class.i
# java -cp . HelloWorld
Hello world
# mv HelloWorld.class HelloWorld.class.o
# cp HelloWorld.class.i HelloWorld.class
# java -cp . HelloWorld
Exception in threadjava "main" java.lang.VerifyError: (class: HelloWorld,
method: meth3 signature: ()V) Stack size too large
Could not find the main class: HelloWorld. Program will exit.
# java -version
java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07)
Java HotSpot(TM) Server VM (build 19.1-b02, mixed mode)
Note, the problem is reprosible as of jdk6u4.
I disassembled classes (with own tools) and there is only difference in the
stack size for 'meth3()'
public Method meth3:"()V"
throws HelloWorld$MyException
stack 1 locals 2
{...}
-->
public Method meth3:"()V"
throws HelloWorld$MyException
stack 0 locals 2
{...}
Should you have any question: feel free to ask me at: dmitry.fazunenko@oracle.com
```https://gitlab.ow2.org/asm/asm/-/issues/3158405 Documentation Bugs in Various Classes2017-12-26T10:38:44Zkivancmuslu5 Documentation Bugs in Various Classes```
The following methods contain documentation bugs relating to Java naming
conventions. The methods either throw an Exception or return an unexpected
value when used as currently documented.
We explain each of these documentation bugs ...```
The following methods contain documentation bugs relating to Java naming
conventions. The methods either throw an Exception or return an unexpected
value when used as currently documented.
We explain each of these documentation bugs in detail below.
We detected these errors using the Checker Framework
(http://types.cs.washington.edu/checker-framework/).
Attached to this bug report is a patch file that corrects all documentation errors.
Bug #1:
The constructor "org.objectweb.asm.ClassReader.ClassReader(String)" is
documented to take a fully qualified name, however it should take a binary name.
If called as documented (with a fully qualified name that is not also a binary
name) the method throws IOException.
Details: The argument string is transformed into a path (by replacing '.' with
'/' and adding .class at the end). Then this path is passed to
ClassLoader.getResourceAsStream(String) method. This method looks if the file
exists in the file system and if it does not, it returns null. Since the
compiled file generated for an inner class has '$' in it (i.e., they follow the
binary name convention), for inner classes, getResourceAsStream will return
null if called with a path that does not include '$' (but includes '/'
instead). Later the result of getResourceAsStream is passed to
ClassReader.readClass(InputStream). This method throws an IOException if the
input is null.
Bug #2:
The method "String org.objectweb.asm.Type.getClassName()" is documented to
return a fully qualified name, however it should return a binary name.
The return value of the method contradicts the documentation when the type
represents an Object.
Details: When the type is an Object, the first and the last elements of the
'buf' (which is the char array for the underlying field descriptor) is
stripped, and '/' is replaced with '.'. Since field descriptors for inner
classes contains '$', and the operation done on the array does not change this
sign, the resulting string will also contain '$' sign. '$' signs are only
contained in binary names.
Bug #3:
The input for the following programs:
org.objectweb.asm.util.CheckClassAdapter.java
org.objectweb.asm.util.TraceClassVisitor.java
org.objectweb.asm.util.ASMifierClassVisitor.java
are documented as a "fully qualified class name or class file name", however
they should be "binary name or class file name".
The input given to these programs are passed to org.objectweb.asm.ClassReader's
constructor. As explained in bug #1, they should be binary names.
```