Java.Lang.VerifyError: tipo incorrecto en la pila de operandos

Suraj P 12 octubre 2023
  1. Comprender java.lang.VerifyError en Java
  2. Ejemplo de java.lang.VerifyError en Java
Java.Lang.VerifyError: tipo incorrecto en la pila de operandos

En este artículo, aprenderemos sobre java.lang.VerifyError en Java.

Comprender java.lang.VerifyError en Java

El java.lang.VerifyError es un error que ocurre en la Java Virtual Machine (JVM) durante el proceso de verificación del bytecode. Este error se produce cuando la JVM detecta que el código de bytes de una clase o método no es válido o viola ciertas restricciones.

Hay varias razones por las que puede ocurrir un java.lang.VerifyError:

  1. Versiones de clase incompatibles: si una clase se compila con una versión diferente del compilador de Java que la versión de la JVM que intenta ejecutar la clase, puede ocurrir un VerifyError. Esto puede suceder si una clase se construye con una versión más reciente de Java pero luego se ejecuta en una JVM más antigua.
  2. Versiones de biblioteca incompatibles: si una clase depende de una biblioteca que tiene una versión diferente a la que se compiló la clase, puede ocurrir un VerifyError.
  3. Uso ilegal de códigos de operación: si una clase o método usa códigos de operación de manera ilegal o no admitida, puede ocurrir un VerifyError.
  4. Formato de archivo de clase no válido: si el archivo de clase está dañado o tiene un formato incorrecto, puede ocurrir un VerifyError.
  5. Uso no válido de la palabra clave final: si a la variable final se le asigna un nuevo valor después de inicializarse, puede ocurrir un VerifyError.
  6. Usar la reflexión para cambiar la accesibilidad de un campo/método privado en una clase cuando un cargador de clases diferente carga la clase.

Para corregir este error, necesitaremos encontrar y corregir la causa del problema. Esto podría implicar volver a compilar la clase con una versión compatible del compilador de Java, actualizar la versión de la biblioteca o eliminar cualquier uso ilegal de códigos de operación.

Si el error se debe al uso de la reflexión, podemos evitarlo no cambiando la accesibilidad de los campos/métodos privados de una clase cargada por un cargador de clases diferente.

En general, es una buena práctica conocer la versión del compilador de Java y las bibliotecas que se utilizan y probar el código con diferentes versiones de JVM para garantizar la compatibilidad. Además, es importante mantener actualizados y en buenas condiciones los archivos y bibliotecas de clases para evitar errores como el java.lang.VerifyError.

Vale la pena señalar que java.lang.VerifyError es un error de tiempo de ejecución y es diferente de java.lang.VerificationError, un error de tiempo de compilación.

Ejemplo de java.lang.VerifyError en Java

Veamos un ejemplo para entenderlo mejor.

Ejemplo uno: Cree dos archivos Java, A.java y B.java.

Archivo A.java:

public class A {
  public A() {
    System.out.println("Instance of A is created");
  }
}

Archivo B.java:

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();
  }
}

Ahora compilamos los archivos:

javac A.java
javac B.java

Ambos archivos se compilan correctamente sin ningún error.

Sin embargo, si cambiamos la definición de la clase A a final, y luego solo recompilamos la clase A y luego ejecutamos el método principal de la clase B, obtenemos el siguiente 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)
     ......
     ......

Este error ocurre porque hemos cambiado la definición de clase A, pero clase B se ejecuta con la versión anterior de clase A.

Ejemplo dos:

Cree tres archivos Java, A.java, B.java y C.java. clase B hereda clase A y clase C contiene el método principal.

Archivo A.java:

public class A {
  public A() {
    System.out.println("Class A instance is created");
  }

  public void print() {
    System.out.println("A::print()");
  }
}

Archivo B.java:

public class B extends A {
  public B() {
    super();
    System.out.println("Class B instance is created");
  }

  public void print() {
    System.out.println("B::print()");
  }
}

Archivo C.java:

public class C {
  public static void _print_(A obj) {
    obj.print();
  }

  public static void main(String[] args) {
    B b = new B();
    C._print_(b);
  }
}

Compilamos los archivos Java por separado y luego ejecutamos el C.java.

javac A.java
javac B.java
javac C.java
java C

La ejecución da como resultado:

Class A instance is created
Class B instance is created
B::print()

Ahora, si cambiamos la definición de la clase B para no extender la clase A, y luego simplemente volvemos a compilar B.java y luego ejecutamos la clase C, obtenemos el siguiente error:

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

Aquí nuevamente, el error ocurre porque hemos cambiado la definición de clase B, pero la clase C se ejecuta con la versión anterior de clase B.

Autor: Suraj P
Suraj P avatar Suraj P avatar

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.

LinkedIn GitHub

Artículo relacionado - Java Error