views:

105

answers:

4

This is what I'm doing:

  1. extract contents of my JRE's rt.jar
  2. extract src.zip of my JDK (same version)

Now, if I copy Runtime.java from the extracted src folder and compile it using javac.exe without any modifications and then put it in the extracted rt folder to finally put everything back in a jar file using jar.exe, everything works as expected. The JRE runs fine.

However, if I make the slightest change to Runtime.java and compile it and put it in rt.jar, the JRE crashes whenever I attempt to start it. This is an example of a slight change that causes the silent crash:

/** Don't let anyone else instantiate this class */
    private Runtime() {
        System.out.println("This is a test.");
    }

Instead of:

/** Don't let anyone else instantiate this class */
    private Runtime() {}

Could anyone tell me why this is causing my JRE to crash?

Thanks in advance.

+1  A: 

That's pretty strange, as I did the same trick with many classes in rt.jar in past.

Can you provide us with the crashed process output?

Vladimir Dyuzhev
How would I get such process output?
Tom
+6  A: 

It's possible that System.out has not been initialised at the time that the Runtime() constructor runs. Usually console output is not considered a "slight" change, but at the wrong time it can invoke way too much stuff that may not be set up at all yet.

Greg Hewgill
Interesting... is there a way to call that line after the JRE has been initialized?
Tom
Easy to test: `if( System.out != null ){ ... }`
Vladimir Dyuzhev
There probably isn't a way to call the `Runtime()` constructor after the JRE has been initialised, because the `Runtime` class is *part of* the JRE. If you're only trying to discover whether you can modify classes inside your `rt.jar` file, you may want to pick some other class to modify, one that isn't involved in JRE startup.
Greg Hewgill
Accepted your answer, thanks. If you know of an object or method that is always called after most core objects have been loaded, I would love to know!
Tom
@Tom: the answer to that would depend on the implementation of your particular JRE. If you have the source code for it, you could try to find the location where the main class `main()` is called, and work backwards from that.
Greg Hewgill
Afraid I don't have the source code for that. I was thinking about some loader event, but don't have much luck so far. Thanks though.
Tom
@tom, A good place to put code that "is always called after most of the core objects have been loaded" is main() or the cinit of the start-up class. 'java -cp . MyClass' will call main() after the JVM is initialized. And the cinit will execute before main(). To circumvent another main, start yours instead. It's _VERY_ bad to modify the Java code: http://java.sun.com/j2se/1.5.0/jre/README An alternative is something like ASM http://asm.ow2.org/ to only affect the runtime classes. And if you're simply trying to learn the internals, grab a good IDE and step through it with a debugger.
nicerobot
Nicerobot, unfortunately I am not in control of the runtime launcher and it's not java.exe but a custom launcher.
Tom
+2  A: 

You're doing this all wrong. You can't distribute that modified JRE for a start, so it is only useful inside your organization . Install a SecurityManager and don't grant your codebase any of the RuntimePermissions you're trying to protect against.

EJP
This is for personal non distribution use only. Thanks for the concerns though.
Tom
+2  A: 

@Tom - I advise you NOT to try to do this:

  • You cannot distribute the modified rt.jar file without violating the Sun binary license.

  • Even if you did, you would not be allowed to call it Java.

  • As you are finding, there are lots of complications that arise when you make changes, particularly when those changes might interfere with the JVM's behind the scenes initialization. And when things blow up during initialization, the JVM often cannot report the problem in an intelligible way.

  • If you do succeed in making the modified rt.jar work for one JRE, there is no guarantee that the same hacks will work for a different version.

  • Nobody in their right mind would knowingly use a modified JVM (especially one modified by a third-party) in a production app.

EDIT : judging from your other questions, I guess you are trying to reverse engineer or modify some third party Java application with a custom launcher. If you provided more information on what you were really trying to do, we might be able to suggest the right way to do it ... rather than using "desperate measures" such as modifying the JRE.

Stephen C
This is for personal non distribution use only, I'm trying to find out more about the application's methods, objects and variables.
Tom
But why? This does not sound like "idle curiosity" to me ...
Stephen C
I want to automate the application, and for that I need to know what state it is in all the time (variables, methods, classes etc).
Tom