Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Letters to the Editor

  • Print
  • Feedback

Java Q&A
"What Version is Your Java Code?"
Vladimir Roubtsov

Static versus lazy resolution



Vladimir,

Good article (as usual), but I disagree with one thing: You wrote that the "JVM is not allowed to complain about a nonexistent method or class unless it is actually needed at runtime." I think the JVM can complain earlier, even before program execution. The Java Language Specification (JLS), Chapter 12.1.2, mentions one extreme of resolution implementation—static. In this case, the JVM performs recursive resolution (before referenced classes are needed) and complains immediately.

I also have interesting practical experience with it, which proves that the HotSpot JVM is neither static nor the laziest implementation. I have a Component A that can directly (without reflection) use Component B in concrete circumstances. My colleagues load-tested Component A, and Component B wasn't on the CLASSPATH. After passing thousands of identical tests (for example, for 10 minutes), suddenly NoClassDefFoundError (with a class from Component B) was thrown. HotSpot probably decided to optimize some classes and load a class from Component B that wasn't needed. I don't think this goes against the specification.

Vojtech Habarta

Vojtech, Regarding your comment about static versus lazy resolution, you might not be interpreting the Java spec 100 percent correctly. The spec does indeed describe two extreme resolution strategies (static and laziest), but also says that regardless of which strategy is used under the hood, the JVM must also semantically give the appearance of lazy resolution only. This is my interpretation of the following sentence in the JLS, Chapter 12.1.2:
The only requirement on when resolution is performed is that any errors detected during resolution must be thrown at a point in the program where some action is taken by the program that might, directly or indirectly, require linkage to the class or interface involved in the error.
That is, there is a difference between detecting errors and actually throwing them. To put it another way, even the most static resolution can detect resolution errors as early as it wants, but they cannot be thrown until the application reaches one of the active use spots. Regarding your other comment: Yes, it is possible faulty (as I interpret it) resolution can cause problems in other cases. In those cases, the approach outlined in the URLTest2 code example (with Class.forName() used to load version-specific classes, if necessary) should continue to work. Vladimir Roubtsov


Java Q&A
"Cracking Java Byte-Code Encryption"
Vladimir Roubtsov

Avoid exploitation



Vladimir,

You've written an interesting article; however, both deficiencies you have identified can be avoided.

First, JVM modification can be handled by checksumming the JVM (rt.jar) against a known value.

Second, accessing the running JVM via the profiling or debugging interface requires launching the VM with certain options. Implementing a native launcher to load the VM and create the secure classloader prevents this exploit.

  • Print
  • Feedback

Resources