Cross Column

Showing posts with label Backward Compatible. Show all posts
Showing posts with label Backward Compatible. Show all posts

Wednesday, January 7, 2015

Java Products: All About Versions

When Java based products evolves, correct operation depends on the knowledge of:
  • What product version to ask for to get particular features
  • What bugs are in what product version 

In this article, we will cover all things about versions in Java products (see also [4-8]).

System.getProperties


There are at least two artifacts that need to be identified for Java product versions:
and each needs to be identified at two levels:
  • Specification
  • Implementation

When the Java application starts, the system properties are initialized with information about the run-time environment, which can be retrieved using java.lang.System.getProperties.  For demonstration, we will use the following code snippets to get system properties:

import java.util.*;

public class PrintJavaSystemProps  {
  public static void main(String [ ] args) {
    Properties p = System.getProperties();
    Enumeration keys = p.keys();
    while (keys.hasMoreElements()) {
      String key = (String)keys.nextElement();
      String value = (String)p.get(key);
      System.out.println(key + ": " + value);
    }
  }
}

To complete, here are the command lines we used to compile and execute the code:

$cat printSysProps.sh

#!/bin/bash
export JAVA_HOME=~/JVMs/jdk-hs
$JAVA_HOME/bin/javac -d . -cp $JAVA_HOME/jre/lib PrintJavaSystemProps.java
$JAVA_HOME/bin/java -cp . PrintJavaSystemProps >systemProperties.txt

General Version Information


From the output of System.getProperties() method, here are the list of relevant version information of Java products:
  • java.version: 1.8.0_40-internal
    • Is displayed on the first line of the output of the java -version command (see example below) in the following format:
    • major_version.minor_version.micro_version[_update_version][-milestone]
  • java.runtime.version: 1.8.0_40-internal-20141227004606.gziemski.jdk8_after-b00
    • Identifies the Java SE JDK/JRE version and build
    • Is displayed on the second line of the output of the java -version command in the following format:
      • major_version.minor_version.micro_version[_update_version][-milestone]-build
  • java.vm.version: 25.40-b23
    • Identifies the JVM implementation version
    • Is displayed on the third line of the output of the java -version command.
  • java.class.version: 52.0
    • Displays the major and minor versions of the class file (see example below)
  • java.specification.version: 1.8
    • Identify the version of the Java Runtime Environment specification that this implementation adhere’s to
  • java.vm.specification.version: 1.8
    • Identifies the version of the JVM specification on which the HotSpot JVM instance is based
The output of the java -version command:

$~/JVMs/jdk-hs/bin/java -version
java version "1.8.0_40-internal"
Java(TM) SE Runtime Environment (build 1.8.0_40-internal-20141227004606.gziemski.jdk8_after-b00)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b23, mixed mode)


The output of javap (i.e., class file disassembler) command:

 ~/JVMs/jdk-hs/bin/javap -verbose ./PrintJavaSystemProps.class |grep 'major\|minor'
  minor version: 0
  major version: 52


Version Identification of the Java Virtual Machine


An implementation of the Java Virtual Machine should be identify both the specification and the implementation as shown below:

java.vm.specification.version: 1.8
java.vm.specification.vendor: Oracle Corporation
java.vm.specification.name: Java Virtual Machine Specification

java.vm.version: 25.40-b23
java.vm.vendor: Oracle Corporation
java.vm.name: Java HotSpot(TM) 64-Bit Server VM


Version Identification of the Java Runtime Environment


An implementation of the Java Runtime  should be identify both the specification and the implementation as shown below:

java.specification.version: 1.8
java.specification.name: Java Platform API Specification
java.specification.vendor: Oracle Corporation

java.version: 1.8.0_40-internal
java.vendor: Oracle Corporation

References

  1. Java™ Product Versioning
  2. Oracle JRockit JVM System Properties
  3. Java Runtime Environment (JRE)
    • The Java Runtime Environment (JRE), also known as Java Runtime, is part of the Java Development Kit (JDK), a set of programming tools for developing Java applications.
    • The Java Runtime Environment provides the minimum requirements for executing a Java application; it consists of the Java Virtual Machine (JVM), core classes, and supporting files.
  4. How to find Oracle WebLogic Server Version? (Xml and More)
  5. How to Determine JDBC Driver Version Installed with WebLogic Server? (Xml and More)
  6. Oracle Products: What Patching, Migration, and Upgrade Mean? (Xml and More)
  7. java.lang.ClassCastException: [I cannot be cast to java.util.List. (Xml and More)
    • The compiler is not backwards compatible because bytecode generated with JDK 7 won't run in Java 1.6 VM (unless compiled with the -target 1.6 flag). But the JVM is backwards compatible, as it can run older bytecodes.
  8. Module Versioning Requirements in Jigsaw Project
    • Upgradeable modules — If a JDK module implements an endorsed standard or standalone technology then it must be possible to use a version of that module from a later release in any phase, i.e., at compile time, build time, or run time.
  9. JAXP: How to Retrieve Its Specification and Implementation Versions (Xml and More)
  10. Java Package: How to Retrieve Its Version Information (Xml and More)

Tuesday, April 2, 2013

java.lang.UnsupportedClassVersionError

When running an application named StoreFrontService, we have run into this exception:
  • java.lang.UnsupportedClassVersionError
In this article, we will examine what it is and how to resolve it.

Class Loading Phases


There are three phases in class loading[1]:
  • Loading
    • See below
  • Linking
    • Bytecode verification[6]
      • Checks the classfile semantics, checks the constant pool symbols, and does type checking
    • Preparation
      • Creates and initializes static fields to standard defaults and allocates method tables
  • Initializing
    •  Runs the class static initializers, and initializers for static fields
For a given Java class or Java interface, the load class phase takes its name, finds the binary in Java classfile format, defines the Java class, and creates a java.lang.Class object to represent that given Java class or Java interface.
The load class phase can throw a NoClassDefFound error if a binary representation of a Java class or Java interface cannot be found. In addition, the load class phase does format checking on the syntax of the classfile, which can throw a ClassFormatError or UnsupportedClassVersionError.

The Exception


In our expriement, we have seen the following exception being thrown:

####<Mar 21, 2013 8:16:43 AM PDT> <Error> <Class Loaders> <sfperf-x6250-10> <MS_1> <[ACTIVE] ExecuteThread: '8' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <> <1363879003661> <BEA-2162500> <Class, oracle.fodemo.storefront.store.service.server.serviceinterface.StoreFrontServiceImpl, was compiled with an incompatible version of Java. Make sure that all the classes needed by the application have been compiled with a compatible java version. java.lang.UnsupportedClassVersionError: oracle/fodemo/storefront/store/service/server/serviceinterface/StoreFrontServiceImpl : unsupported classversion 51.0
java.lang.UnsupportedClassVersionError: oracle/fodemo/storefront/store/service/server/serviceinterface/StoreFrontServiceImpl : unsupported classversion 51.0
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:14

      
This turns out to be that our application StoreFrontService was compiled in JDK 7 (class version: 51)[7] and we were running it on JRockit bundled with Java 1.6 VM (class version: 50). The compiler is not backwards compatible[2] because bytecode generated with JDK 7 won't run in Java 1.6 VM (unless compiled with the -target 1.6 flag[3]). But the JVM is backwards compatible, as it can run older bytecodes.

References

  1. Java Performance by Charlie Hunt, Binu John, David Dagastine 
  2. Is JDK “upward” or “backward” compatible?
  3. Cross-Compilation Options
  4. Java SE 6 vs. JRE 1.6 vs. JDK 1.6 - What do these mean?
  5. JRockit Version Information
  6. Java Virtual Machine Specification
  7. Unsupported major.minor version 51.0

© Travel for Life Guide. All Rights Reserved.

Analytical Insights on Health, Culture, and Security.