The follow code compiles but causes a java.lang.VerifyError. The error occurs even if the run() method is not executed.
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
public class TestCase {
public static void main(String[] args) {
new TestCase().run();
}
public void run() {
class Inner {
}
Map<String, Inner> map = new HashMap<>();
Function<String, Inner> function = (name) -> {
Inner i = map.get(name);
if (i == null) {
i = new Inner();
map.put(name, i);
}
return i;
};
function.apply("test");
}
}
The Error:
Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
Exception Details:
Location:
TestCase.lambda$0(Ljava/util/Map;Ljava/lang/String;)LTestCase$1Inner; #20: invokespecial
Reason:
Type 'java/util/Map' (current frame, stack[2]) is not assignable to 'TestCase'
Current Frame:
bci: #20
flags: { }
locals: { 'java/util/Map', 'java/lang/String', 'TestCase$1Inner' }
stack: { uninitialized 15, uninitialized 15, 'java/util/Map' }
Bytecode:
0000000: 2a2b b900 2d02 00c0 0032 4d2c c700 15bb
0000010: 0032 592a b700 344d 2a2b 2cb9 0037 0300
0000020: 572c b0
Stackmap Table:
append_frame(#33,Object[#50])
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2688)
at java.lang.Class.getMethod0(Class.java:2937)
at java.lang.Class.getMethod(Class.java:1771)
at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
However, if I move the 'Inner' class to be an inner class of TestCase (instead of declared in a method), the error goes away. Or, if I use an anonymous class to define the Function, the error goes away. It seems to be an issue with a class declared in the method and the use of a lamba.
Is this a JVM bug? Or am I missing something? I am using Oracle's Java 8. The error happens both on the command line and within Eclipse 4.4.
EDIT:
I upgraded to the latest JDK:
java version "1.8.0_11"
Java(TM) SE Runtime Environment (build 1.8.0_11-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.11-b03, mixed mode)
When compile via javac manually and run it works fine. If I run the class compiled by Eclipse, it doesn't. So now I suspect that the Eclipse compiler has a bug.
verify error is thrown when your compiler generates a code that is not verifiable by verifier.
when the "verifier" detects that a class file, though well formed, contains some sort of internal inconsistency or security problem. So it is clearly an issue with your eclipse compiler as you have suggested. it is unable to properly compile these constructs.
Related
I have Java 19, and I am attempting to do some simple pattern-matching on a record that I created. However, Java is giving me a very confusing compilation error. Here is the simplest example I could make that causes the error.
public class ExpressionTypeIsASubsetOfPatternType
{
public record Triple(int a, int b, int c) {}
public static void main(String[] args)
{
System.out.println("Java Version = " + System.getProperty("java.version"));
final Triple input = new Triple(1, 2, 3);
if (input instanceof Triple t)
{
System.out.println("Made it here");
}
}
}
And here is the error that it gives me when I try to run/compile.
$ java ExpressionTypeIsASubsetOfPatternType.java
ExpressionTypeIsASubsetOfPatternType.java:15: error: expression type Triple is a subtype of pattern type Triple
if (input instanceof Triple t)
^
1 error
error: compilation failed
Surprisingly enough, googling this error showed up nothing useful. I am so used to punching in an error and immediately seeing the problem. I imagine that it is because this feature is so new.
Anyways, the closest thing I could find is a bug that is related, but definitely not the same issue that I am dealing with.
Finally, here is the relevant info about my java version.
$ java --version
openjdk 19 2022-09-20
OpenJDK Runtime Environment (build 19+36-2238)
OpenJDK 64-Bit Server VM (build 19+36-2238, mixed mode, sharing)
$ javac --version
javac 19
Java is just being "nice": it recognizes that the test will always succeed (because input is known to be a Triple, which is already a subtype of the test type Triple), so it produces an error telling you that you're doing something useless (with a roundabout message).
This is the same idea that makes
void foo() {
return;
return; // error: unreachable statement
}
an error: there is a useless piece of code that might indicate (serious) programmer error, so the compiler forces you to rethink the code.
The relevant section of the JLS is 15.20.2, which says
InstanceofExpression:
...
RelationalExpression instanceof Pattern
...
The following rules apply when instanceof is the pattern match operator:
...
If the type of the RelationalExpression is a subtype of the type of the Pattern, then a compile-time error occurs.
I.e. this is indeed an intended part of the language and not just a compiler bug or something.
I am Trying to use records preview-feature with cannonical constructors in Eclipse .
public class Example {
public static void main(String[] args) {
record Range() {
Range {
}
}
new Range();
}
}
However, at run time a verify error is caused.
Exception in thread "main" java.lang.VerifyError: Constructor must
call super() or this() before return Exception Details: Location:
Example$1Range.(II)V #36: return Reason:
Error exists in the bytecode Bytecode:
0000000: 1b1c a400 22bb 000b 5912 0d05 bd00 0f59
0000010: 031b b800 1153 5904 1cb8 0011 53b8 0017
0000020: b700 1dbf b1 Stackmap Table:
same_frame(#36)
at Example.main(Example.java:10)
This happens both in eclipse 2020-06 with JDK 14 and eclipse 2020-19 with JDK 15.0.1 and eclipse 15 support.
There is no problem running it from the command line with bin\java and no error is thrown then.
Is this working for anyone else on their eclipse?
Are there any workarounds?
I recently installed jdk10. I was doing normal code and it is not working.
Am I doing something wrong here?
Please see the code and Exception stacktrace.
As far as I understand there should be no reason for such behaviour.
import com.bean.College;
public class Student {
interface Club {
<T> T get(College<T> key);
}
private Club club;
Student() {
Object obj = club.get(new College<>() {});
}
}
The imported College class is:
public class College<T> {
int id;
protected College() {
}
College(int id){
this.id=id;
}
}
On compiling this the javac compiler crashes with the following stacktrace:
java.lang.NullPointerException
at jdk.compiler/com.sun.tools.javac.comp.Flow$FlowAnalyzer.visitApply(Flow.java:1233)
at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1634)
at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
at jdk.compiler/com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:396)
at jdk.compiler/com.sun.tools.javac.comp.Flow$FlowAnalyzer.visitVarDef(Flow.java:987)
at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCVariableDecl.accept(JCTree.java:956)
at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
at jdk.compiler/com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:396)
at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57)
at jdk.compiler/com.sun.tools.javac.comp.Flow$FlowAnalyzer.visitBlock(Flow.java:995)
at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:1020)
at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
at jdk.compiler/com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:396)
at jdk.compiler/com.sun.tools.javac.comp.Flow$FlowAnalyzer.visitMethodDef(Flow.java:962)
at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:866)
at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
at jdk.compiler/com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:396)
at jdk.compiler/com.sun.tools.javac.comp.Flow$FlowAnalyzer.visitClassDef(Flow.java:925)
at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:774)
at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
at jdk.compiler/com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:396)
at jdk.compiler/com.sun.tools.javac.comp.Flow$FlowAnalyzer.analyzeTree(Flow.java:1325)
at jdk.compiler/com.sun.tools.javac.comp.Flow$FlowAnalyzer.analyzeTree(Flow.java:1315)
at jdk.compiler/com.sun.tools.javac.comp.Flow.analyzeTree(Flow.java:216)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1393)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1367)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:965)
at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:306)
at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:165)
at jdk.compiler/com.sun.tools.javac.Main.compile(Main.java:57)
at jdk.compiler/com.sun.tools.javac.Main.main(Main.java:43)
It is a reported unresolved bug. The bug is planned to be resolved in jdk 11.
JDK-8203195-Anonymous class type inference results in NPE
Type: Bug
Status: In Progress
Priority: P2
Resolution: Unresolved
Affects Version/s: 9, 10, 10.0.1, 11
Fix Version/s: 11
Component/s: tools
Labels: dcsfai reproducer-yes webbug
Subcomponent: javac
CPU: generic
OS: generic
https://bugs.openjdk.java.net/projects/JDK/issues/JDK-8203195?filter=allopenissues
However, there is a work around mentioned in the bug description which states:
Interestingly, changing A.java to do the following:
Object baz => foo.foo(new B<Object>() {});
or changing foo/B.java to the
following:
package foo;
public class B<T> {
B(int baz) { }
protected B() { }
}
results in a successful compilation.
Even tho the bug reports status is still open using java 11 fixes that issue for me
I had exactly the same error and I couldn't find any solution. Even when I tried to build using java 11 (some say it is fixed there) it still failed with the same error.
But the error was just MISLEADING. After some changes in code and retries (I removed some code..), I found that the actual error was some missing libraries, which I added in the classpath and the build was successful!
I am attempting to write a class for converting domain POJO's into QuickFixJ messages. When I try to create a new order message as so:
quickfix.fix44.NewOrderSingle order = new quickfix.fix44.NewOrderSingle();
The following exception is thrown in the logs:
Exception Details:
Location:
quickfix/fix44/NewOrderSingle.get(Lquickfix/field/SettlType;)Lquickfix/field/SettlType; #2: invokevirtual
Reason:
Type 'quickfix/field/SettlType' (current frame, stack[1]) is not assignable to 'quickfix/CharField'
Current Frame:
bci: #2
flags: { }
locals: { 'quickfix/fix44/NewOrderSingle', 'quickfix/field/SettlType' }
stack: { 'quickfix/fix44/NewOrderSingle', 'quickfix/field/SettlType' }
Bytecode:
0000000: 2a2b b600 3057 2bb0
It seems this error happens when attempting to merge two versions of Fix Message Fields together but as far as I know I am not doing this. I am using the same code as found in the QuickFixJ unit tests A variation of the same code works in this example, it is after a connection is applied through the initiator object. I am using the apache.servicemix.bundles.quickfix instead of the QuickFix-all.jar because it contains some fields i need to add to other messages.
I am unsure why I am not able to call a simple constructor of an object. The constructor in the jar is as follows:
public NewOrderSingle()
{
getHeader().setField(new MsgType("D"));
}
Is there another possible cause for this error I havent thought of? I am stumped
I had this problem and had to revert to QuickFIX 1.5.2
quickfixj message factory produces bad type on operand stack using qf 1.6.0 and java 1.8.0_45
It's a known issue according to the user group. See the attached question...
While I've tried to use the following code snippet with the Groovy in-operator explanation the VerifyError has occured. Have you guys any idea about?
The code and console output is below.
class Hello extends ArrayList {
boolean isCase(Object val) {
return val == 66
}
static void main(args) {
def myList = new Hello()
myList << 55
assert 66 in myList
assert !myList.contains(66)
}
}
The error log:
Exception in thread "main" java.lang.VerifyError: (class: Hello, method: super$1$stream signature: ()Ljava/util/stream/Stream;) Illegal use of nonvirtual function call
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:259)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:116)
The code origin from the topic How does the Groovy in operator work?.
Update:
Groovy Version: 1.8.6 JVM: 1.6.0_45 Vendor: Sun Microsystems Inc. OS: Linux
Check this out.
It's for Java, but generally problem is, that you are using wrong library versions. The class is there, but different version than expected.
http://craftingjava.blogspot.co.uk/2012/08/3-reasons-for-javalangverfiyerror.html
Probably you have messed up Groovy or Java SDK installations.