Bug 516 - Building under Java 7 produces some class files with post-Java-6 version numbers
Summary: Building under Java 7 produces some class files with post-Java-6 version numbers
Status: RESOLVED FIXED
Alias: None
Product: Jogl
Classification: JogAmp
Component: util (show other bugs)
Version: 2
Hardware: All all
: P4 minor
Assignee: Sven Gothel
URL:
Depends on:
Blocks:
 
Reported: 2011-08-31 22:10 CEST by Wade Walker
Modified: 2012-01-22 23:55 CET (History)
0 users

See Also:
Type: ---
SCM Refs:
gluegen 64639b805a32338385421f168e12c1ef7f749d00 gluegen 9df0473afdceca1403751b5f54f53c7ec86b3015
Workaround: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Wade Walker 2011-08-31 22:10:02 CEST
If you compile gluegen and jogl with Java 7, you see this when you try to run those JARs under Java 6:

java.lang.UnsupportedClassVersionError:
javax/media/opengl/GLCapabilitiesImmutable : Unsupported major.minor version
51.0
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClassCond(Unknown Source)
    at java.lang.ClassLoader.defineClass(Unknown Source)
    at java.security.SecureClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.access$000(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)

So some javac ant task must be using the JVM's default target instead of 1.6.
Comment 1 Wade Walker 2011-12-02 17:06:34 CET
Do we want our build to always produce Java-1.5-compatible class files, or are we just checking the source files to make sure they are Java 1.5 or less?

If we mean to produce Java-1.5-compatible class files, we'd need to add -target and -bootclasspath options to our javac tasks. Right now we only  use the -source option.

Building on CentOS 5.6 with JDK 1.7.0_01, you can check the .class file versions like this:

find build -name '*.class' | xargs -I {} javap -v {} | grep 'major version'

I see this for all class files:

  major version: 51
  major version: 51
  major version: 51
  ...

If they were Java-1.5-compatible, the major version would be 49 instead of 51.
Comment 2 Sven Gothel 2011-12-02 18:03:12 CET
Good catch. Good question.

For sure the source compatibility is important.

AFAIK 1.6 is available on all desktops. Java7 would be language version 1.7 ?
Sure we shall avoid the latter.

Maybe we just add your suggested javac flags and build for 1.5 binary
compatibility since we should comply w/ those.
These 1.5 binaries shall also work fine w/ higher java versions AFAIK.

Are there any benefits of having binaries > version 1.5  [for source version 1.5] ?
Comment 3 Wade Walker 2011-12-07 04:41:38 CET
The problem with targeting 1.5 JARs when compiling with JDK 1.6 or 1.7 is that you have keep a separate 1.5 version of rt.jar to point your -bootclasspath to. So we'd have to add that rt.jar to the project tree somewhere. If you'd like me to try this, just let me know.

Right now we're essentially requiring Java 1.6 to use JOGL, since all our JARs are 1.6. This isn't a problem on most desktops, but maybe it's a problem on Android?

There are a few advantages to a 1.7 JAR (see http://openjdk.java.net/projects/jdk7/features/), but nothing that seems mandatory, unless you wanted to try using the new XRender pipeline (http://mail.openjdk.java.net/pipermail/challenge-discuss/2008-March/000054.html).
Comment 4 Wade Walker 2012-01-03 16:38:25 CET
It looks like we have two possible solutions here:

1. Compile the distributed JOGL with the original JDK 1.5
2. Add JDK 1.5's lib JARs to the JOGL project and set javac -bootclasspath
   to point to them (they're ~40MB)

The first way was cited as the most reliable in this blog entry:

http://blogs.oracle.com/darcy/entry/how_to_cross_compile_for

but it might be painful for you to set up. But the second way requires 40 MB of JARs to be added to our source tree :(

Please let me know how you'd like me to proceed.
Comment 5 Sven Gothel 2012-01-04 13:24:55 CET
Thank you for going through these details, Wade.

+++

Right now we do the following:

- All supported 'Java' platforms use JRE/JDK 1.6.* (latest)
  - Linux, Windows, MacOSX, ..

- Android uses a 1.5 (1.6'ish compatible) set of class files
  compatible w/ the current 1.6 JRE rt.jar (?)

- We use '-source 1.5' compatible tags (if some are missing, it's a bug)

+++

Regardless whether the current setup suits us or
use a genuine 1.5 or 1.6 source/target build,
we need to setup our tools to properly specify the build result - agreed!

This will be true at least when JDK 1.6 reaches EOL and we shall use
JDK 1.7 but still want to produce proper 1.5/1.6 builds.

Comment 4, Option 1 is IMHO not feasible, since we may run out of supported JDKs
for the running platform - at least won't receive bug fixes (of javac, etc.).

Comment 4, Option 2 is feasible IMHO, but we cannot redistribute the rt.jar
or any other part of the JRE not just because of bandwidth but legal issues.

+++

What we can do is provide an Ant environment variable 'target.rt.jar' w/ full path to the 
respective rt.jar matching 'target.sourcelevel' (currently 1.5). 
If 'target.rt.jar' is given, we set the javac target to 'target.sourcelevel' 
and the bootclasspath to 'target.rt.jar'.

We can utilize this setup for our Jenkins nodes and ofc our own developer machines.

Other developer not willing to go through these hurdles would be fine as well,
their produced binaries would just not be compatible w/ older JREs.

Such a setup should also suit a Java 7 environment AFAIK.

If you agree, I may try the new environment variable 'target.rt.jar' within the next days
within our system.
Comment 6 Wade Walker 2012-01-04 15:13:16 CET
Defining a target.rt.jar Ant variable sounds like a good solution. Let me know when you do this, and I'll verify that it works on my platforms.

It looks like the last version of Java 1.5 is still available at http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-javase5-419410.html#jdk-1.5.0_22-oth-JPR, so we (or users who want to build JOGL) can get the old rt.jar from there.
Comment 7 Sven Gothel 2012-01-22 23:55:22 CET
Adaptations to this patch are made in all subprojects (joal*, jogl* and jocl*) !

+++

    Fix Bug 516 (Determine Java Version); Minor fixes (jogamp/common/** ..)
    
    Current minimum requirements are:
       - Java 1.6 (Level 6.0)
       - Android SDK API Level 9 (Version 2.3 Gingerbread)
    
    Official production builds are performed w/ Java 1.6.
       - Java 1.6 (Level 6.0)
       - Android SDK API Level 9 (Version 2.3 Gingerbread)
    
    Android supports Java language level 6.0.
    Nevertheless, it cannot be guaranteed whether the Android API
    supports all classes and methods of Java 1.6.
    It is required for JogAmp developers to validate Android compatibility
    by an Android crosscompilation build.
    
    Current GlueGen code utilizes some minor Java 1.6 features
    which could be replaced, however it's not desired at this point
    since we have no mode hard Java 1.5 constraints.
    
    Notes:
      - On OS X 10.5.8, only the 64bit version of Java6 is available
        and hence the only supported one on Leopard.
    
    +++
    
    Pushing determination of host (compiletime) and target (runtime) Java version
    to 'jogamp-env.xml'.
    
    jogamp-env.xml uses:
      env: SOURCE_LEVEL  -> propery: target.sourcelevel  def.: ${ant.java.version} >=1.6 (!)
      env: TARGET_LEVEL  -> propery: target.targetlevel  def.: ${ant.java.version} >=1.6 (!)
      env: TARGET_RT_JAR -> propery: target.rt.jar       def.: ${java.home}/lib/rt.jar
    
    Either all above values are set, or none at all (default),
    otherwise a build error is being thrown.
    
    Further more we have the compiletime properties:
      host.sourcelevel  def.: ${ant.java.version} >= 1.6 (!)
      host.targetlevel  def.: ${ant.java.version} >= 1.6 (!)
      host.rt.jar       def.: ${java.home}/lib/rt.jar
    
    +++
    
    - 'javac.memorymax' defaults to 1024m now.