Friday Free Stuff* everybody!
official business first.

this is your finger on the pulse of what's new at Sun Microsystems. September 21; 11 a.m. EDT. free admission. sign up for a reminder.
now let's see what we've in terms of a fabulous package of prizes*.

holy cow, (no offense intended) would you look at that! it's a t-shirt, a frisbee, three Java pins, a card that gets you a free ringtone on java.com, a yellow foam java.com mini armchair (don't really get that one), a Java Everywhere button and a Java watch (ladies model; sorry guys)!! full disclosure: minor issue with the watch. but it doesn't keep it from being the singular-must have fashion accessory for the fall.
oh, can you believe it! it's a regular cornucopia, people. one of you lucky* readers is going to get this package of prizes* shipped to your doorstep, gratis.
I was thinking that this week I'd pick the winner* using a centuries-old, tested, rigorous methodology.
But then Click and Hack said they'd officiate!
(See, I'm responsive. Manjunath tells me he wants more meat in this blog. I get all over it.)
Here is your chance to win* the Friday Free Stuff grand prize*... Please join me in savoring this week's puzzler! (Courtesy Click and Hack)
Way back in 1998, a bunch of thread
primitives were
deprecated
because they were unsafe. A particularly heinous example of what could
be done with one of these primitives follows:
public static void sneakyThrow(Throwable t) {
Thread.currentThread().stop(t); // deprecated
}
This nasty little method does exactly
what the throw statement does, except that it completely bypasses all
exception checking by the compiler: You can (sneakily) throw any
exception (checked or otherwise) from any point in your code, and the
compiler won't bat an eyelash.
Now, the puzzler: It turns out that it is still possible to write a functionally equivalent method without using any deprecated methods. In fact, Click and Hack know of two ways to do it, one of which takes advantage of Tiger (JDK 5.0) features. Can you come up with either or both? Extra points if you discover a technique unknown to Click and Hack.
post your answers as comments to this blog. you've got till Tuesday. (Monday is a holiday here in the U.S.)happy Friday, everybody!
mary
* Friday Free Stuff is not a contest. It's me giving away stuff that I personally own to somebody I choose. I pay for shipping with stamps that I buy at the post office. Sun employees can play but are not eligible to win* the prize.*
$ cat A.java public class A { public static void sneakyThrow(Throwable t) { B.sneakyThrow(t); } public static void main(String[] args) { sneakyThrow(new Throwable()); } } $ cat B.java public class B { public static void sneakyThrow(Throwable t) { } } $ jikes A.java B.java $ vim B.java $ cat B.java public class B { public static void sneakyThrow(Throwable t) throws Throwable { throw t; } } $ jikes B.java $ java -cp . A java.lang.Throwable at A.main(A.java:6) Exception in thread "main"Posted by Bob Lee on September 03, 2004 at 03:08 PM PDT #
Posted by Click and Hack the Type-it Brothers on September 03, 2004 at 10:21 PM PDT #
Mary, I believe that the foam armchair is a cell phone holder. Well I have something similar that was sold as such.
Posted by Alan Hargreaves on September 04, 2004 at 02:02 AM PDT #
Posted by zakłady bukmacherskie on September 04, 2004 at 05:54 AM PDT #
Posted by Unknown on September 04, 2004 at 03:46 PM PDT #
The Roubtsov article describes essentially the same technique that Bob Lee came up with. As we said to Bob, you can do better than that. After all, there is free stuff to be won. We're looking for code that you can just compile and use, no cheap modify-the-class-file or create-a-new-class-file-after-compiling-the-client tricks.
Regards,
Click and Hack
Posted by Click and Hack the Type-it Brothers on September 04, 2004 at 04:27 PM PDT #
import java.lang.reflect.*; public class ThreadStop { public static void sneakyThrow(Throwable t) throws Exception { Method resume0 = Thread.class.getDeclaredMethod("resume0", null); Method stop0 = Thread.class.getDeclaredMethod("stop0", new Class[] { Object.class }); resume0.setAccessible(true); stop0.setAccessible(true); Thread thread = Thread.currentThread(); resume0.invoke(thread, null); stop0.invoke(thread, new Object[] { t }); } public static void main(String[] args) throws Exception { sneakyThrow(new Exception("Die!")); } }Posted by Kris Schneider on September 04, 2004 at 05:51 PM PDT #
Please read the problem carefully. You're supposed to write a method that is declared to throw no exceptions whatsoever, but is in fact capable of throwing any exception. Your sneakyThrow method is declared to throw Exception--sort of takes all the fun out of it:)
Click and Hack
Posted by Click and Hack the Type-it Brothers on September 04, 2004 at 09:20 PM PDT #
Posted by James on September 06, 2004 at 04:57 AM PDT #
Posted by James on September 06, 2004 at 05:01 AM PDT #
Please read our responses to anonymous (and Bob Lee) above. This article has already been mentioned. It involves modifying the class file after compiling the client. In order to win the free stuff, you have to come up with an ordinary old Java program that displays the same behavior as sneakyThrow. We assure you it's possible. We know of two ways to do it, and there may be more.
Regards,
Click and Hack
Posted by Click and Hack the Type-it Brothers on September 06, 2004 at 06:50 AM PDT #
Posted by James on September 07, 2004 at 12:27 AM PDT #
Posted by Mridul on September 07, 2004 at 03:31 AM PDT #
Posted by Mridul on September 07, 2004 at 06:03 AM PDT #
public class DieJavaDie { private static class StackSmasher implements Runnable { public void run() { Object o = null; o.hashCode(); } } private static class SneakyThreadGroup extends ThreadGroup { private Throwable toThrow; public SneakyThreadGroup(ThreadGroup parent, String name, Throwable toThrow) { super(parent, name); this.toThrow = toThrow; } public void uncaughtException(Thread t, Throwable e) { super.uncaughtException(t, toThrow); } } public static void main(String []args) { ThreadGroup parent = Thread.currentThread().getThreadGroup(); ThreadGroup child = new SneakyThreadGroup(parent, "child", new ClassCastException("0wn3d")); Thread runner = new Thread(child, new StackSmasher()); runner.start(); } }Uses ThreadGroups uncaughtException handling to sneakily exchange an exception for another. It uses a separate thread that creates a harmless exception and then can swap in anything you like in the thread group exception propagation chain.
I could have made main a method that accepts a parameter, but the idea is the same anyway: use helper class to work around thread group backdoor, throw runtime exception, change it in the backdoor in the desired exception, profit.
cheers, dalibor topic
Posted by Dalibor Topic on September 07, 2004 at 08:30 AM PDT #
Posted by Bob Lee on September 07, 2004 at 09:05 AM PDT #
public class ThreadStop { public static void sneakyThrow(final Throwable t) { InvocationHandler h = new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { throw t; } }; Object proxy = Proxy.newProxyInstance(ThreadStop.class.getClassLoader(), new Class[] { Cloneable.class }, h); proxy.toString(); } ... }But the stack trace looks something like:java.lang.reflect.UndeclaredThrowableException at $Proxy0.toString(Unknown Source) at ThreadStop.sneakyThrow(ThreadStop.java:16) at ThreadStop$2.run(ThreadStop.java:24) Caused by: java.lang.InterruptedException: Die! ... 1 moreMeaning that the only place you see the orignal Throwable is as the cause for the UndeclaredThrowableException. That's gotta be better than my first post ;-). BTW, even if I come up with anything worthy I'm not planning on claiming any of the Free Stuff 'cause I got hooked-up not too long ago...Posted by Kris Schneider on September 07, 2004 at 09:21 AM PDT #
Posted by mary on September 07, 2004 at 09:26 AM PDT #
public static void sneakyThrow(Throwable t) { throw new UndeclaredThrowableException(t); }Which doesn't quite cut it I think...Posted by Kris Schneider on September 07, 2004 at 11:39 AM PDT #
Nope, sorry, as you suggested, your <tt>sneakyThrow</tt> method throws a specific unchecked exception (<tt>UndeclaredThrowableException</tt>) rather than an arbitrary, possibly checked, exception. It's not hard to throw an unchecked exception with a checked exception as its cause, e.g.:
throw new RuntimeException(myThrowable);Regards,
Click and Hack the Type-it Brothers
Posted by Click and Hack the Type-it Brothers on September 07, 2004 at 11:50 AM PDT #
Posted by Bob Lee on September 07, 2004 at 11:50 AM PDT #
static Throwable throwable; public static class Evil { public Evil() throws Throwable { throw throwable; } } public static synchronized void sneakyThrow(Throwable t) { try { throwable = t; Evil.class.newInstance(); } catch (IllegalAccessException e) {} catch (InstantiationException e) {} }Posted by Bob Lee on September 07, 2004 at 12:03 PM PDT #
Posted by Kris Schneider on September 07, 2004 at 12:14 PM PDT #
Posted by Kris Schneider on September 07, 2004 at 12:31 PM PDT #
public class DieJavaDie { private static class StackSmasher implements Runnable { public void run() { Object o = null; o.hashCode(); } } private static class SneakyThreadGroup extends ThreadGroup { private Throwable toThrow; public SneakyThreadGroup(ThreadGroup parent, String name, Throwable toThrow) { super(parent, name); this.toThrow = toThrow; } public void uncaughtException(Thread t, Throwable e) { super.uncaughtException(t, toThrow); } } private static class SneakyThrower { public static void sneakyThrow(Throwable t) { ThreadGroup parent = Thread.currentThread().getThreadGroup(); ThreadGroup child = new SneakyThreadGroup(parent, "child", t); Thread runner = new Thread(child, new StackSmasher()); runner.start(); } } public static void main(String []args) { // demonstrate the technique: // despite no method in this code being declared as throwing an // exception, this call will result in an // ClassCastException with the desired message being thrown SneakyThrower.sneakyThrow(new ClassCastException("Own3d, 0nc3 m0r3")); } }Okay, this one implements the same API from the example. I hope it's obvious now ;)Posted by Dalibor Topic on September 07, 2004 at 01:25 PM PDT #
Posted by Dalibor Topic on September 07, 2004 at 01:31 PM PDT #
Posted by Bob Lee on September 07, 2004 at 01:45 PM PDT #
Click and Hack
Posted by Click and Hack the Type-it Brothers on September 07, 2004 at 01:51 PM PDT #
Posted by Kris Schneider on September 07, 2004 at 01:58 PM PDT #
Posted by Bob Lee on September 07, 2004 at 02:09 PM PDT #
Posted by Kris Schneider on September 07, 2004 at 02:58 PM PDT #
Posted by Bob Lee on September 07, 2004 at 03:21 PM PDT #
Posted by Chris Nokleberg on September 10, 2004 at 10:03 AM PDT #
On the contrary, we would have awarded your solution second prize! It clearly obeys the constraints of the problem, and demonstrates initiative on your part. Furthermore, dynamic byte code generation is an important technique: It forms the basis for reflection and JSPs (among other things). It's an advanced technique and an "extra-linguistic mechanism," the sort of thing that you shouldn't use unless you need to, but if you need it, there's no substitute.
Regards,
Click and Hack
P.S. No one commented on the Tiger solution! Was anyone else surprised by it? We sure were when we discovered it!
Posted by Click and Hack, the Type-it Brothers on September 14, 2004 at 10:28 AM PDT #
Posted by ropo on December 12, 2004 at 06:36 PM PST #