Comments (21)
@RoiSoleil : could you please attach a self contained project that has all required libraries to reproduce the problem?
Why do you think if the 3rd party library can't parse bytecode, it is a bug in JDT and not in the 3rd party bytecode parser?
from eclipse.jdt.core.
Actually I can reproduce without the "Indexer" from Jandex.
Just have Bytecode Outline view opened in 4.27 master and get this error:
Cannot decompile: [Working copy] A.java [in test [in src [in A2]]]
package test
import java.util.*
class A
static void main(String[])
class EList
EList(T ...)
Iterator<T> iterator() null
java.lang.IllegalArgumentException
at org.objectweb.asm.signature.SignatureReader.parseType(SignatureReader.java:249)
at org.objectweb.asm.signature.SignatureReader.accept(SignatureReader.java:114)
at org.objectweb.asm.util.Textifier.appendJavaDeclaration(Textifier.java:1349)
at org.objectweb.asm.util.Textifier.visitMethod(Textifier.java:418)
at org.eclipse.jdt.bcoview.asm.CommentedClassVisitor.visitMethod(CommentedClassVisitor.java:164)
at org.eclipse.jdt.bcoview.asm.CommentedClassVisitor.visitMethod(CommentedClassVisitor.java:1)
at org.objectweb.asm.util.TraceClassVisitor.visitMethod(TraceClassVisitor.java:230)
at org.objectweb.asm.tree.MethodNode.accept(MethodNode.java:645)
at org.objectweb.asm.tree.ClassNode.accept(ClassNode.java:468)
at org.eclipse.jdt.bcoview.asm.DecompilerHelper.getDecompiledClass(DecompilerHelper.java:44)
at org.eclipse.jdt.bcoview.views.BytecodeOutlineView.decompileBytecode(BytecodeOutlineView.java:1458)
at org.eclipse.jdt.bcoview.views.BytecodeOutlineView.refreshView(BytecodeOutlineView.java:1054)
at org.eclipse.jdt.bcoview.views.BytecodeOutlineView.handlePartVisible(BytecodeOutlineView.java:951)
at org.eclipse.jdt.bcoview.views.EditorListener.partOpened(EditorListener.java:121)
at org.eclipse.ui.internal.PartService$10.run(PartService.java:193)
from eclipse.jdt.core.
Hi, Jandex maintainer here (the bytecode parsing library in question).
Here's a minimal reproducer:
import java.util.function.Supplier;
public class MyList<T> {
public MyList(T... elements) {
}
public static Supplier<? extends MyList<Object>> supplier() {
return MyList<Object>::new;
}
}
Compile with ECJ like this:
java -jar ecj-4.26.jar -17 MyList.java
And inspect the generated bytecode using javap
:
javap -v -p MyList.class
You'll notice that the generated signature for the synthetic lambda method is ()+LMyList<Ljava/lang/Object;>;
. That doesn't conform to the grammar in the JVMS, chapter 4.7.9.1.
from eclipse.jdt.core.
ECJ generates this (4.21 and 4.27 master are generating same code):
private static ? extends MyList<java.lang.Object> lambda$1();
descriptor: ()LMyList;
flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
Signature: #29 // ()+LMyList<Ljava/lang/Object;>;
Code:
stack=3, locals=0, args_size=0
0: new #1 // class MyList
3: dup
4: iconst_0
5: anewarray #3 // class java/lang/Object
8: invokespecial #30 // Method "<init>":([Ljava/lang/Object;)V
11: areturn
LineNumberTable:
line 1: 0
javac generates this
private static MyList lambda$supplier$0();
descriptor: ()LMyList;
flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
Code:
stack=3, locals=0, args_size=0
0: new #3 // class MyList
3: dup
4: iconst_0
5: anewarray #4 // class java/lang/Object
8: invokespecial #5 // Method "<init>":([Ljava/lang/Object;)V
11: areturn
LineNumberTable:
line 8: 0
from eclipse.jdt.core.
Aside: one funny thing is that javap
doesn't hesitate to print private static ? extends MyList<java.lang.Object> lambda$1();
, which clearly contains an invalid return type :-)
from eclipse.jdt.core.
? extends MyList<java.lang.Object>
as return type for synthetic lambda$1
method seem to be strange, differs from simple MyList
of javac.
from eclipse.jdt.core.
Because javac doesn't emit the signature. (And hence javap
prints a return type based on the descriptor.)
from eclipse.jdt.core.
@othomann, @stephan-herrmann : could you please look at the lambda generation above? It is not a recent regression, so is not something I can easily spot.
from eclipse.jdt.core.
Nice to see that it's quickly handled ;) Thx
from eclipse.jdt.core.
? extends MyList<java.lang.Object>
as return type for syntheticlambda$1
method seem to be strange, differs from simpleMyList
of javac.
I think from a type inference p.o.v. that return type is correct (modulo wildcard capture), since the method implements Supplier<? extends MyList<Object>>
. Simple MyList
, OTOH, is correct from a JVM p.o.v.
Without having debugged the sample, my guess is: ecj sees good reason to generate a signature attribute (not needed by the JVM, but useful for tools and reflection), but then JVMS doesn't specify syntax for this type. In other similar bugs we learned that the compiler should simply refuse generating the signature, reasoning that even if the compiler should normally generate this attribute, we should rather err on the side of missing information in the byte code, rather than emitting illegal signatures. We probably need to implement more heuristics, which signatures should be avoided.
This could be further complicated if it's the same implementation where internally JDT expects some signature always, and now for code generation it must refuse to compute a signature.
from eclipse.jdt.core.
Any news about that ?
from eclipse.jdt.core.
See https://mail.openjdk.org/pipermail/compiler-dev/2015-January/009268.html - javac never generates Signature attributes for synthetic lambda body methods.
See also: https://bugs.eclipse.org/bugs/show_bug.cgi?id=449063
I'll investigate
from eclipse.jdt.core.
? extends MyList<java.lang.Object>
as return type for syntheticlambda$1
method seem to be strange, differs from simpleMyList
of javac.I think from a type inference p.o.v. that return type is correct (modulo wildcard capture), since the method implements
Supplier<? extends MyList<Object>>
. SimpleMyList
, OTOH, is correct from a JVM p.o.v.
I'll start with that assertion.
Without having debugged the sample, my guess is: ecj sees good reason to generate a signature attribute (not needed by the JVM, but useful for tools and reflection), but then JVMS doesn't specify syntax for this type. In other similar bugs we learned that the compiler should simply refuse generating the signature, reasoning that even if the compiler should normally generate this attribute, we should rather err on the side of missing information in the byte code, rather than emitting illegal signatures. We probably need to implement more heuristics, which signatures should be avoided.
I went hunting for uses of ExtraCompilerModifiers.AccGenericSignature where we see a clear (&= ~ExtraCompilerModifiers.AccGenericSignature), but see only two uninteresting cases.
I am fairly certain what you are alluding is to "non-denotable types" and the compiler punting from whatever operation (diamond inference) it is doing when encountering one of those.
I agree, we should suppress the generation of this attribute when we encounter a non-denotable type.
(See org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression.validate(...).ValidityInspector - this itself is fairly "polluted" and can't be used as is as it has side effects)
This could be further complicated if it's the same implementation where internally JDT expects some signature always, and now for code generation it must refuse to compute a signature.
from eclipse.jdt.core.
I have raised a PR that is undergoing test - apart from the code freeze period coming in the way, there is also some problems with my old and new eclipse identities colliding in various manner. So, this will take a while to get integrated into mainline, but if someone wants to test against their tooling/library environments, then the patch can be grabbed (after Jenkins blesses it)
from eclipse.jdt.core.
More prior art FYI: https://bugs.eclipse.org/bugs/show_bug.cgi?id=494198 where we approximate by erasure rather than dropping the signature.
from eclipse.jdt.core.
Thanks, for good or bad, I will try aligning with this prior strategy.
from eclipse.jdt.core.
Food for thought: This fix ought to leave in us a better place but I wonder if "approximate by erasure" results in coarseness. I wonder if we should reach for the bounds suitably instead in the case of wildcards.
from eclipse.jdt.core.
Food for thought: This fix ought to leave in us a better place but I wonder if "approximate by erasure" results in coarseness. I wonder if we should reach for the bounds suitably instead in the case of wildcards.
When asking which strategy would be 'better', do we have any metric for this, i.e., what would be our goals (in which priority):
- don't crash
- don't let tools reading our class files crash
- don't violate JVMS
- mimic (exactly?) what javac does
- use our own judgement which strategy (roughly within JVMS) might provide most value to tools and reflection
from eclipse.jdt.core.
See #1048 - while the GSFE goes away. encoding the generic signature as ()Ljava/util/stream/Stream<TT;>; appears problematic - I am yet to fully analyze.
from eclipse.jdt.core.
Food for thought: This fix ought to leave in us a better place but I wonder if "approximate by erasure" results in coarseness. I wonder if we should reach for the bounds suitably instead in the case of wildcards.
When asking which strategy would be 'better', do we have any metric for this, i.e., what would be our goals (in which priority):
- don't crash
- don't let tools reading our class files crash
- don't violate JVMS
- mimic (exactly?) what javac does
- use our own judgement which strategy (roughly within JVMS) might provide most value to tools and reflection
We are using the "use our own approach ..." here to accomplish some of the earlier bullets. Javac doesn't emit generic signature for synthetic methods at all - I think we should in the cases where the signature is non denotable do exactly that.
Lengthy discussion here: #414
from eclipse.jdt.core.
FTR, pursuant to discussion at #414, the PR #1070 replaces the approximate-by-erasure strategy implemented for this ticket with "skip generic signature emission for synthetic methods if non denotable types are involved" strategy.
from eclipse.jdt.core.
Related Issues (20)
- [Patterns] Secret local/pattern bindings variable slots appear to be reaped later than they should be HOT 1
- [Patterns] Missing boxing conversion after instanceof leads to verify error
- completion returns no results with pattern matching HOT 10
- [Sealed classes] Inconsistent type hierarchy on sealed interface when used with other from different level in class hierarchy HOT 3
- Allow enums to have more constants HOT 4
- WeakReference -> SoftReference HOT 2
- [Patterns] ECJ allows illegal modifiers with RecordPattern HOT 3
- [Patterns] ECJ allows record pattern to have dimensions HOT 2
- [22] VerifyError when String template expression is used as part of condition HOT 4
- Circular dependency error when using JPMS HOT 3
- [String Templates] Compilation error when Template Processor used in unconditional for loop
- [formatter] Format License header in module-info.java like in every other java-class HOT 14
- False Positive Potential Resource Leak Warnings With Inherited AutoCloseable Classes HOT 4
- [22][dom ast][rewrite] DOM AST Rewrite Support for JEP 447 Super After Statement HOT 3
- [22] String Template expression as standalone statements
- bug class nor found HOT 1
- [22] Implement Elements#getEnumConstantBody() HOT 1
- [Release notes] Show fixed bugs in release notes HOT 3
- APT plugin does not use projects JDK for annotation processing HOT 3
- An (optional) p2 repo built with this repo HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from eclipse.jdt.core.