开发者

Hacking into java.lang.Object: calling custom external class crashes JVM

I'm playing around with editing java.lang.Object for the Java Runtime Environment. I realize that there are probably better ways to do what I want, but that is not what my question is about.

Basically I've added a constructor to java.lang.Object which gets called everytime an object is created. I'm waiting for a certain class to load like so:

public Object() {
       if (hookEnabled) {
            hookEnabled = false;
        objectCount++;
        if (objectCount > objectStartCount) {
            if (this.getClass() != null) {
                String name = this.getClass().getName();
                if ((!name.startsWith("java.")) && (!name.startsWith("javax.")) && (!name.startsWith("launcher.")) && (!name.startsWith("sunw.")) && (!name.startsWith("com.sun.")) && (!name.startsWith("sun.")) && (!name.startsWith("org.xml.")) && (!name.startsWith("org.w3c.")) && (!name.startsWith("org.omg.")) && (!name.startsWith("org.ietf."))) {
                    if (!hasHooked) {
                        hasHooked = true;

//startup beep
        java.awt.Toolkit.getDefaultToolkit().beep();

        //load interface
        javax.swing.JFrame frame = new javax.swing.JFrame("");
        frame.setBounds(0, 0, 400, 400);
        frame.setAlwaysOnTop(true);
        frame.setVisible(true);

                    }
                }
            }
        }
         hookEnabled = true;
        }
    }

This works fine. It adds a window to whatever application is being run by the JVM.

However, when making a simple change by moving the JFrame code into a separate class, and calling that call the JVM simply crashes:

public Object() {
            if (hookEnabled) {
            hookEnabled = false;
        objectCount++;
        if (objectCount > objectStartCount) {
            if (this.getClass() != null) {
                String name = this.getClass().getName();
                if ((!name.startsWith("java.")) && (!name.startsWith("javax.")) && (!name.startsWith("launcher.")) && (!name.startsWith("sunw.")) && (!name.startsWith("com.sun.")) && (!name.startsWith("sun.")) && (!name.startsWith("org.xml.")) && (!name.startsWith("org.w3c.")) && (!name.startsWith("org.omg.")) && (!name.startsWith("org.ietf."))) {
                    if (!hasHooked) {
                        hasHooked = true;
                        (new tvmh.DFVMH()).setup(); 
                    }
                }
            }
        }
           hookEnabled = true;
        }
    }

--

 package tvmh;

    public class DFVMH {
        public void setup() {
            //startup beep
            java.awt.Toolkit.getDefaultToolkit().beep();

            //load interface
            javax.swing.JFrame frame = new javax.swing.JFrame("");
            frame.setBounds(0, 0, 400, 400);
            frame.setAlwaysOnTop(true);
            frame.setVisible(true);
        }
    }

The same happens when I try to create a java.util.Timer object.

Interestingly enough, the above does work if I make DFVMH an inline class (internal c开发者_C百科lass) of java.lang.Object itself.

Could anyone tell me why such behaviour would happen? And is there any way to safely call such custom class?


Tinkering with the innards of the JVM like this is very risky. There are all sorts of hidden dependencies at the low levels of the JVM that can break. JVM bootstrap is a very delicate process.

For instance, the most likely reason you are seeing a crash rather a StackOverflowError is that your change has broken all object construction ... including construction of the error object.

And I suspect that your guard code is ineffective because this.getClass().getName() may be causing a String object to be created. So the fatal recursion happens before you get to your guard.

(Incidentally, your hasHooked flag introduces a race condition.)


My advice is "Don't do it!".


What do you mean by 'it crashes'?.

Isn't it StackOverflowException? Your new tvmh.DFVMH() is actually a constructor all too. So it runs through your 'overriden' Object constructor.

If you already play like this, how about adding the tvmh.DFVMH to stop list of packages/classes?


Just a quick thought: new tvmh.DFVHM() becomes a new object, which also derives from java.lang.Object, meaning your custom constructor code will be run again before the first one has finished. I'm guessing "hasHooked" should guard against that, but how is that variable defined? If that guard doesn't work, this sequence it will recurse infinitely.

If you make DFVMH an inline class it's name will probably start with "java.lang[...]" (it's in java.lang.Object, after all) and will thus not get through the long if statement with all the name.startsWith.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜