Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What can you throw in Java?

Conventional wisdom says you can only throw objects that extend Throwable in Java, but is it possible to disable the bytecode verifier and get Java to compile and run code that throws arbitrary objects - or even primitives?

I looked up the JVM's athrow and it will pop the first objref on the operand stack; but would it check if said reference points to a Throwable at run time?

like image 323
NullUserException Avatar asked Apr 21 '11 21:04

NullUserException


People also ask

Can we throw object in Java?

In Java, exceptions are objects. When you throw an exception, you throw an object. You can't throw just any object as an exception, however, only objects whose class descends from Throwable . Throwable serves as the base class for an entire family of classes, declared in java.

Which exception we can throw?

We can throw either checked or unchecked exception. The throw keyword is mainly used to throw custom exceptions.

Can you throw a string in Java?

You can only throw something that implements Throwable. So no, you can't throw a String . You would have to make something that implements throwable, then throw it. Probably better to have it implement exception though and have your exception message be the String.

Where is throw used in Java?

The throw keyword is used to create a custom error. The throw statement is used together with an exception type. There are many exception types available in Java: ArithmeticException , ClassNotFoundException , ArrayIndexOutOfBoundsException , SecurityException , etc.


1 Answers

It depends on your JVM implementation. According to the Java VM specification it is undefined behavior if the object is not Throwable.

The objectref must be of type reference and must refer to an object that is an instance of class Throwable or of a subclass of Throwable.

In section 6.1, "The Meaning of 'Must'":

If some constraint (a "must" or "must not") in an instruction description is not satisfied at run time, the behavior of the Java virtual machine is undefined.

I wrote a test program using the Jasmin assembler which does the equivalent of throw new Object(). The Java HotSpot Server VM throws a VerifyError:

# cat Athrow.j  .source Athrow.j .class public Athrow .super java/lang/Object  .method public <init>()V     aload_0     invokenonvirtual java/lang/Object/<init>()V     return .end method  .method public static main([Ljava/lang/String;)V     .limit stack 2      new java/lang/Object     dup     invokenonvirtual java/lang/Object/<init>()V     athrow      return .end method  # java -jar jasmin.jar Athrow.j  Generated: Athrow.class  # java Athrow Exception in thread "main" java.lang.VerifyError: (class: Athrow, method: main signature: ([Ljava/lang/String;)V) Can only throw Throwable objects 

Disabling the bytecode verifier allows the athrow to execute and the JVM appears to crash when it tries to print the exception's details. Compare these two programs, the first which throws an Exception, the second which is the above test program which throws an Object. Notice how it exits in the middle of a printout:

# java -Xverify:none examples/Uncaught Exception in thread "main" java.lang.Exception         at examples.Uncaught.main(Uncaught.j) # java -Xverify:none Athrow Exception in thread "main" # 

Of course, disabling the bytecode verifier is dangerous. The VM proper is written to assume that bytecode verification has been performed and therefore does not have to typecheck instruction operands. Beware: the undefined behavior that you invoke when you circumvent bytecode verification is much like the undefined behavior in C programs; anything at all can happen, including demons flying out of your nose.

like image 175
John Kugelman Avatar answered Sep 30 '22 22:09

John Kugelman