Java lang verifyerror bad type on operand stack

Saved searches

Use saved searches to filter your results more quickly

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

java.lang.VerifyError: Bad type on operand stack in putfield #17

java.lang.VerifyError: Bad type on operand stack in putfield #17

Comments

ProGuard version 6.2.2 but this has been happening for a while now with older versions too.

This is when optimizations are on. With dontoptimize this error is gone. This is the full error:

java.lang.VerifyError: Bad type on operand stack in putfield Exception Details: Location: com/company/fj.(Ljava/lang/String;Z)V @6: putfield Reason: Type 'com/company/fj' (current frame, stack[0]) is not assignable to 'com/company/rest/b' (constant pool 29) Current Frame: bci: @6 flags: < >locals: < 'com/company/fj', 'java/lang/String', integer >stack: < 'com/company/fj', 'java/lang/String' >Bytecode: 0000000: 2ab7 002c 2a2b b500 1d2a 1cb5 001e b1 

Here is my configuration options:

 target '13' overloadaggressively allowaccessmodification mergeinterfacesaggressively keepparameternames optimizationpasses 5 dontshrink dontusemixedcaseclassnames repackageclasses 'com.company' 

Not sure how I can help with this. What information do you need from me?

The text was updated successfully, but these errors were encountered:

Adding dontshrink is difficult as we have classes that we use dynamically and I would have to go through all of them and «keep» them manually. and I don’t even know them all so it will be a tedious process. If that is very important for you and will help with debugging the issue, I could try doing it. But until a few months ago, all was working fine with optimizations enabled and dontshrink . Then after some changes in our code, that exception started happening and it still is today.

I was worried that you would need a reproduction. Let me see what I can do about that in the next days. Unfortunately we have a big app so that might be difficult. I’ll let you know how it goes.

We would need something, at least the class file of the class that fails verification.

If -dontshrink is too difficult, could you at least try disabling some optimizations that might result in structural changes:

With this configuration — optimizations ‘!class/merging/*’ , the project works fine.

If you want the class file, please give me an email to send it to and tell me whether you want the version before or after ProGuard and, if after, what configuration to use.

Thanks for the test, that would be an indication that disabling shrinking is really the culprit. Fyi: when classes are being merged, the class that is merged into another one is not immediately being removed, this is done in the subsequent shrinking step. Now when you disable shrinking the class is not removed, but it might be out of sync. We will take a look into such cases and remove such merged classes in any case. Is disabling class merging for now an acceptable solution?

Читайте также:  Php array unique recursive

If you mean whether that configuration I pasted above is a solution — absolutely, even dontoptimize is. So am I to understand that you think you know what the issue is and you require nothing else from me for now? I’ll let you know whether the problem is resolved for any new version that you release.

Thank you for the support!

We have a clue, but without any more input its impossible to confirm. In any way, using optimization with -dontshrink is not advised. Disabling class merging will avoid most of the problems. That would also explain why it suddenly started to appear: which classes are being merged depends on many factors, even slight changes in the respective code can lead to different results.

We will try to ensure that merged classes are properly cleaned up even with dontshrink enabled, but the priority of this is not very high.

The low priority is totally fine — not a problem at all. Just a question — after you fix it some day, will it be safe to use dontshrink with optimizations enabled? You keep saying that’s not a good idea but dontshrink is mandatory for us (and perhaps for lots of users) and I would like to enable optimizations and know that this is OK and not unadvised.

It depends your use-case. From your configuration that you posted above, I assume that you have enabled obfuscation. Now when you access classes dynamically you will have to add a keep rule as otherwise they are renamed and you will not be able to access them via reflection.

Most of the time, if your app / library works with obfuscation enabled, you will get shrinking for free as all necessary keep rules are already in place.

I am not aware of many users that use -dontshrink, in fact thats the biggest benefit of ProGuard for most users, especially for Android applications.

You’re right, mostly. For example, when I tried running our app without dontshrink , it blew up because the class that is used in resources/META-INF/services/ch.qos.logback.classic.spi.Configurator was removed. What I would have to do to run without dontshrink is to keep explicitly that class but allow obfuscation because that is what is done now by default — the class is obfuscated, protected from removal, and the resources/META-INF/services/ch.qos.logback.classic.spi.Configurator file is modified with the obfuscated name. There are probably more cases like this, but you are right that there aren’t that many. I’ll try to «fix» them and remove dontshrink if you’re saying that this is better. Do you understand what I mean?

Yes, I understand, what you describe makes sense. Such cases are an exception of course, but they should be very limited, if you can add explicit rule for such classes and can enable dontshrink you will gain a lot of benefit from using ProGuard.

A couple of more cases that come to my mind:

  1. JAX-RS endpoints — they are not used anywhere and have to be preserved manually when dontshrink is not used.
  2. When writing a library (or an application which, for example, exposes a plugin API and some utility methods) — practically nothing should be removed as that’s the point — there are a bunch of methods that are entry points and nothing is used internally.
Читайте также:  Пакет визуал для питона

Especially in the second case dontshrink is very useful and without it it’s going to be very painful (and error-prone) to protect everything from removal.

Now that I think about it, can’t I just do keep allowoptimization: true, allowobfuscation: true, ‘class com.company.* < *; >‘ to have the same effect as dontshrink and not hit the problems that you mention when using it?

@1: I dont know how JAX-RS endpoints are declared. Via annotations or config files? Does Proguard replace them properly?

@2: you need to define the public API of your library that will also not be obfuscated, so dontshrink does not help you here imho. Basically you define the public API of your library and everything that is accessed dynamically, the remaining things will only be kept if they are actually accessed statically. Remaining things are removed.

Thats is how most of our customers apply ProGuard / DexGuard on their library.

OK, in order to not prolong this conversation too much, could you just tell me what you think of my last paragraph from the previous message (out of curiosity):

Now that I think about it, can’t I just do keep allowoptimization: true, allowobfuscation: true, ‘class com.company.* < *; >‘ to have the same effect as dontshrink and not hit the problems that you mention when using it?

Thank you again for your time!

no that does not help. You basically allow optimization of these classes, but prevent shrinking of them, so ending up with the same problem as using -dontshrink globally.

I see. Thanks! Let’s keep this issue open until you’ve fixed it if you’re OK with that.

You can’t perform that action at this time.

Источник

Java.Lang.VerifyError: Bad Type on Operand Stack

Java.Lang.VerifyError: Bad Type on Operand Stack

  1. Understand java.lang.VerifyError in Java
  2. Example of java.lang.VerifyError in Java

In this article, we will learn about java.lang.VerifyError in Java.

Understand java.lang.VerifyError in Java

The java.lang.VerifyError is an error that occurs in the Java Virtual Machine (JVM) during the bytecode verification process. This error is thrown when the JVM detects that the bytecode of a class or method is invalid or violates certain constraints.

Incompatible class versions: If a class is compiled with a different version of the Java compiler than the version of the JVM that is trying to run the class, a VerifyError can occur. This can happen if a class is built with a more recent version of Java but is then run on an older JVM.

Incompatible library versions: If a class depends on a library that has a different version than the one the class was compiled with, a VerifyError can occur.

Illegal use of opcodes: If a class or method uses opcodes in an illegal or unsupported way, a VerifyError can occur.

Invalid class file format: If the class file is corrupted or has the wrong format, a VerifyError can occur.

Invalid use of the final keyword: If the final variable is assigned a new value after it’s initialized, a VerifyError can occur.

Читайте также:  Python debugging with idle

Using reflection to change the accessibility of a private field/method in a class when a different classloader loads the class.

To fix this error, we will need to find and correct the cause of the problem. This could involve recompiling the class with a compatible version of the Java compiler, updating the library version, or removing any illegal use of opcodes.

If the error is due to the use of reflection, we can avoid it by not changing the accessibility of private fields/methods of a class loaded by a different classloader .

In general, it’s a good practice to be aware of the version of the Java compiler and libraries being used and to test the code with different versions of the JVM to ensure compatibility. Additionally, it’s important to keep the class files and libraries up to date and in good condition to avoid errors like the java.lang.VerifyError .

It’s worth noting that java.lang.VerifyError is a runtime error, and it’s different from java.lang.VerificationError , a compile-time error.

Example of java.lang.VerifyError in Java

Let’s see an example to understand it better.

Example one: Create two Java files, A.java and B.java .

public class A   public A()    System.out.println("Instance of A is created");  >  > 
public class B extends A   public B()   super();  System.out.println("Instance of B is created");  >  public static void main(String[] args)   B obj = new B();  >  > 

Both files compile properly without any errors.

However, if we change the definition of the class A to final , and then only recompile the class A and then execute the main method of class B , we get the following error:

Exception in thread "main" java.lang.VerifyError: Cannot inherit from final class  at java.lang.ClassLoader.defineClass1(Native Method)  at java.lang.ClassLoader.defineClass(ClassLoader.java:760)  .  . 

This error occurs as we have changed the definition of class A , but class B is executed with the older version of class A .

Create three Java files, A.java , B.java , and C.java . class B inherits class A and class C contains the main method.

public class A   public A()   System.out.println("Class A instance is created");  >   public void print()   System.out.println("A::print()");  > > 
public class B extends A   public B()   super();  System.out.println("Class B instance is created");  >   public void print()   System.out.println("B::print()");  > > 
public class C   public static void _print_(A obj)   obj.print();  >   public static void main(String[] args)   B b = new B();  C._print_(b);  > > 

We compile the Java files separately and then execute the C.java .

javac A.java javac B.java javac C.java java C 
Class A instance is created Class B instance is created B::print() 

Now, if we change the definition of the class B not to extend the class A , and then just recompile B.java and then execute the class C , we get the following error:

Exception in thread "main" java.lang.VerifyError: Bad type on operand stack Exception Details:  .  . 

Here again, the error occurs because we have changed the definition of class B , but the class C is executed with the older version of class B .

A technophile and a Big Data developer by passion. Loves developing advance C++ and Java applications in free time works as SME at Chegg where I help students with there doubts and assignments in the field of Computer Science.

Related Article — Java Error

Источник

Оцените статью