I have created my own UI component in Java. It has model and a few of model's methods can throw my exception called ModelException. I want to use this component in JRuby but I can't raise my ModelException:
raise ModelException # it cause TypeError: exception class/object expected
So I tried to create method throwing ModelException in Java and then invoke it in JRuby:
public class ScriptUtils {
private ScriptUtils() {
}
public static void throwModelException(ModelException e)
throws ModelException {
throw e;
}
}
but when I call throwModelException from JRuby I get:
org.jruby.exceptions.RaiseException: Native Exception: 'class app.ui.ModelException'; Message:
; StackTrace: app.ui.ModelException
...
Caused by: app.ui.ModelException
this native exception cannot be handled by Java code.
Any ideas how to throw Java exception in JRuby and catch it in Java?
This is a complete re-write of my original answer as I originally mis-read your question!
You can raise Java exceptions and catch them in JRuby but you need to be a bit careful how you call raise:
raise ModelException
Will cause a type error (as you saw) because to JRuby ModelException looks like a plain constant. Remember that in Ruby class names are constants. You can raise direct subclasses of Ruby Exception like this, e.g.:
raise RuntimeError
But I think such subclasses are a special case. Those that are actually Java classes you need to call with a constructor:
raise ModelException.new
Or whatever constructor/s you have for that class. An instance of ModelException, in JRuby, is a subclass of Exception because JRuby creates it as such, but the Java class itself isn't. All this is assuming that you have imported your ModelException class correctly.
As for your second example, I couldn't replicate that error at all. As long as I created the exception object correctly, as above, it worked and I didn't see any complaints about "Native Exception" at all. So I'm not sure what is happening there, sorry.
Related
The following text is from "Effective Java", Item 2:
The traditional Abstract Factory implementation in Java has been the
Class object, with the newInstance method playing the part of the
build method. This usage is fraught with problems. The newInstance
method always attempts to invoke the class’s parameterless
constructor, which may not even exist. You don’t get a compile-time
error if the class has no accessible parameterless constructor.
Instead, the client code must cope with InstantiationException or
IllegalAccessException at runtime, which is ugly and inconvenient.
Also, the newInstance method propagates any exceptions thrown by the
parameterless constructor, even though newInstance lacks the
corresponding throws clauses. In other words, Class.newInstance breaks
compile-time exception checking. The Builder interface, shown above,
corrects these deficiencies.
Please go to this link for full text.
I've been able to follow everything before, "In other words..". Can someone please explain how does newInstance break compile-time exception checking and how does Builder pattern fixes it.
'newInstance' doesn't know ahead of time (at compile time) what exceptions could be thrown, as a normal class method would (because of the way code dependencies are built, and because a class has to make known which exceptions it throws).
The Builder pattern uses a class that takes a request (usually via a method) and creates a new object instance based on steps (most likely defined in that class).
Conceptually a non-abstract factory, and builder are very similar.
public class Main {
private int i;
public Main() throws IOException {
throw new IOException();
}
public static void main(String[] args) {
Class c = Main.class;
try {
c.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
In my opinion, if we use class.newInstance() method, we will never know the exactly exception will be thrown by the construction even though the exception is a checked exception and the checked exception isn't shown at the method signature. Just like the example above. If we use class.newInstance(), we will forget to handle the IOException and then get a "broken object". But the Builder pattern won't. Sorry for my pool english and hope you can understand.
Currently I'm making a mod for Vanilla Minecraft server, which I'm not able to modify the underlying code. Now I'm trying to alter the stack trace printed when I accidentally run into a bug with the re-obfuscated version (attached to the server.jar file downloaded directly from the official Mojang site), making it "deobfuscated", like what Minecraft Forge does. (I've tried finding what I need in the source of Forge, but I guess I'm not experienced enough to read it. :<)
Since the exceptions and the stack traces are sometimes thrown and printed by the server codes which I can't modify, I guess using custom Exception file may not help at all.
I've tried to run the main method using a custom Thread with custom getStackTrace() method, which of course doesn't work at all, since the stack trace generation is implemented in the native codes of the JVM.
The codes below are some examples:
Main.java (Cannot be modified and will be renamed during re-obfuscation)
package underlying.cannot.be.modified
public class Main
{
public static void main(String[] args)
{
...
new SomeClass().someMethod();
...
}
}
SomeClass.java (Cannot be modified and will be renamed during re-obfuscation)
package underlying.cannot.be.modified
public class SomeClass
{
...
public void someMethod()
{
...
try
{
...
}
catch(Exception e)
{
/*
* An example of an exception thrown in the underlying codes
* which cannot be modified.
*/
e.printStackTrace();
}
...
}
...
}
For instance, the following obfuscation mapping is applied:
underlying.cannot.be.modified.Main -> underlying.cannot.be.modified.Main
main(String[]) -> main
underlying.cannot.be.modified.SomeClass -> A
someMethod() -> a
and a stack trace may be like:
at A.a (?:?)
at underlying.cannot.be.modified.Main (?:?)
I'd like to make the stack trace printed as:
at underlying.cannot.be.modified.SomeClass.someMethod (?:?)
at underlying.cannot.be.modified.Main (?:?)
(Of course I hold the mapping which I can implement into my code, and the main() method above is called by my custom code instead of called by the JVM directly. :>)
Does anyone know how to modify the behavior of the getStackTrace() method, by either Java codes, reflection, or even through the custom native codes, with the least required external libraries possible? Thanks!
This is a simplified class that describes my problem:
public class Main {
enum Test{
First(method()){ // Unhandled exception type Exception
// ...
};
Test(Object obj){
//...
}
}
static Object method() throws Exception{
// ...
if (someCondition){
throw new Exception();
}
}
}
Above someCondition depends on device and some situations and I can not decide in about it now, also as you can see, I do not want to catch Exception in method.
Yes. It is a compilation error.
No. There is no special syntax to deal with this.
I do not want to catch Exception in method.
Unfortunately if you throw a checked exception, it has to be caught further up the call stack. That is a fundamental design principal for the Java language, and one that the compiler enforces strictly.
In this, case there is no way to catch the checked exception. Hence, if you are going to call a method in enum constant parameter (as per your code), the method cannot throw a checked exception1.
Here is a possible workaround, though this is probably a bad idea:
public class Main {
enum Test{
First(methodCatchingException()){
// ...
};
Test(Object obj){
//...
}
}
static Object method() throws Exception{
// ...
if (someCondition){
throw new Exception();
}
}
static Object methodCatchingException() {
try {
return method();
} catch (Exception ex) {
throw new SomeRuntimeException("the sky is falling!", ex);
}
}
}
Another way to look at this problem is to ask yourself what should happen with the exception if the compiler let you write that ... and an exception was thrown? Where would it go?
You can't catch it ... because the enum initialization is like a static initialization.
If the Java runtime completely ignored the thrown exception, that would be really bad.
If the Java runtime crashed, then the model of checked exceptions is broken.
So, what this is saying to me is that the Java language design is right, the Java compiler is right ... and the real problem here is in your application design:
You should not be propagating a checked exception here. If an exception occurs in this context it is categorically NOT a recoverable error.
Maybe it is inadvisable to use an enum for this ... because of the potential for non-recoverable initialization errors.
(Note that if this method call terminates due to an unchecked exception, it will turn it into an ExceptionInInitializerError. In addition, the JVM will mark the enum class as uninitializable, and will throw an NoClassDefFoundError if your application attempts to use it; e.g. via Class.forName(...).)
I assume that Exception is used here for illustration purposes. It is a bad thing to declare methods as throws Exception or to throw new Exception(...)
1 - I had a look at the JLS for something to back this up. As far as I can tell, the spec does not mention this situation. I'd have expected to see it listed in JLS 11.2.3. However, it is clear that a compiler cannot allow a checked exception to propagate at that point as it would "break" the model of how checked exceptions work.
I don't think you want to be throwing a checked exception here (which is what Exception is). The reason: you're invoking the call of method inside of the constructor of Test. There's really not a clean way to deal with it.
While the obvious choice here is to switch to RuntimeException, I want you to reconsider throwing the exception in the first place. Since your enum will only ever have First declared in it, does it really make sense for it to throw an exception when it's being instantiated? Personally, I don't think it does; whatever dangerous operation it's doing should be deferred until you want to invoke it, and then would you want to throw your exception.
public void useSkill(Champion target, int skillIndex, boolean enemy) throws UtilitiesException {
if (champSkills[skillIndex].getManaCost() > this.currentMana) {
throw new RequirmentNotMetException("Not Enough mana");
}
I would like to throw a requirmentNotMetexception (which extends the utilitiesException) with message "not enough mana".
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Unhandled exception type UtilitiesException
at eg.edu.guc.lol.game.champions.Tank.useSkill(Tank.java:27)
at eg.edu.guc.lol.game.champions.asfasf.main(asfasf.java:33)
I want to use exceptions to show the user that the champion has no mana instead of using an if/else statement checking the mana of the champion and printing not enough mana.
Somebody in the call stack has to handle the RequirmentNotMetException, or every method on the call stack has to declare that it throws the exception (or a parent), or the exception has to extend RuntimeException. Evidently, your main method is not declared as throwing it, and I wouldn't expect it to. So, check up the call chain, identify who should handle the exception, have that method handle it, and have everything in between declare itself as throwing it.
Your useSkill method looks fine. It declares the exception type in the throws clause of the method signature, so the problem is likely where this method is invoked. It looks to me like you're getting the error runtime, which might indicate that you have not recompiled all the classes using the Tank class after you have changed the signature. Still, you need to either catch the exception where you're using the useSkill method, or just pass it on by declaring those methods to throw that exception type as well.
Either you have not imported the UtilitieException or your UtilitiesException class has errors.
What happens if a JNI dll throws a Java exception, and the java method definition doesn't declare that exception (no throws clause)?
Code:
private native void jniDoSomething(int someValue);
Exception will be thrown anyway.
Just have checked this.
I think such behaviour is because that throws keyword doesn't affect the native code anyway. There is no ability to check if the native code throws the appropriate exception and even in header file there are no mentioning about exceptions.