Getting class to compile under JDK 1.5 AND 1.6

Discussion in 'Java' started by Chris, Dec 13, 2006.

  1. Chris

    Chris Guest

    I've got a puzzling problem. Our code runs fine under JDK 1.5. I
    downloaded JDK 1.6 today, recompiled, and got errors.

    The trouble is that one of our classes implements the java.sql.ResultSet
    interface, and they changed the interface to include more methods. For
    example:

    public RowId getRowId(int columnIndex);

    Ok, no problem, I just went ahead and implemented that method in our
    code (and just threw an UnsupportedOperationException in the method body).

    The trouble is that now the code won't compile under JDK 1.5 because
    RowId is a new class in 1.6 and doesn't exist in 1.5.

    So I appear to have an impossible situation: no way to make the code
    compilable under 1.5 and 1.6 at the same time.

    What's the way out?
    Chris, Dec 13, 2006
    #1
    1. Advertising

  2. Chris wrote:
    > ...Our code runs fine under JDK 1.5. I
    > downloaded JDK 1.6 today, recompiled, and got errors.

    ....
    > The trouble is that now the code won't compile under JDK 1.5 because
    > RowId is a new class in 1.6 and doesn't exist in 1.5.
    >
    > So I appear to have an impossible situation: no way to make the code
    > compilable under 1.5 and 1.6 at the same time.
    >
    > What's the way out?


    I have ebeen thinking on similar problems related
    to cross-compilation. Although I have not actually
    tested it yet, I figure it *might* be possible to get a
    clean compile by specifying a -bootclasspath
    pointing to the 1.5 rt.jar, with the 1.6 rt.jar added
    to the standard classpath.

    Andrew T.
    Andrew Thompson, Dec 13, 2006
    #2
    1. Advertising

  3. Chris

    Chris Guest

    Andrew Thompson wrote:
    > Chris wrote:
    >> ...Our code runs fine under JDK 1.5. I
    >> downloaded JDK 1.6 today, recompiled, and got errors.

    > ...
    >> The trouble is that now the code won't compile under JDK 1.5 because
    >> RowId is a new class in 1.6 and doesn't exist in 1.5.
    >>
    >> So I appear to have an impossible situation: no way to make the code
    >> compilable under 1.5 and 1.6 at the same time.
    >>
    >> What's the way out?

    >
    > I have ebeen thinking on similar problems related
    > to cross-compilation. Although I have not actually
    > tested it yet, I figure it *might* be possible to get a
    > clean compile by specifying a -bootclasspath
    > pointing to the 1.5 rt.jar, with the 1.6 rt.jar added
    > to the standard classpath.
    >


    What would that mean at runtime, though?

    Maybe I should just test this, but what if I leave the extra methods off
    my class, compile it under 1.5, and then run it under 1.6? Does it blow
    up when my class is loaded?
    Chris, Dec 13, 2006
    #3
  4. Chris wrote:

    > What would that mean at runtime, though?
    >
    > Maybe I should just test this,


    Maybe you should.

    >..but what if I leave the extra methods off
    > my class, compile it under 1.5, and then run it under 1.6?


    Any code that can run successfully in 1.5, should work in
    1.6 (1.7, 1.8) - barring a JVM bug of some sort(, or reliance
    on bugs that happen in 1.5).

    >...Does it blow
    > up when my class is loaded?


    No. Whay would you think that might pose a problem,
    as opposed to the other way around (running 1.6 code,
    written in the 1.6 class format - in 1.5)?

    Andrew T.
    Andrew Thompson, Dec 13, 2006
    #4
  5. Chris

    Daniel Dyer Guest

    On Wed, 13 Dec 2006 23:10:48 -0000, Chris <> wrote:

    > Andrew Thompson wrote:
    >> Chris wrote:
    >>> ...Our code runs fine under JDK 1.5. I
    >>> downloaded JDK 1.6 today, recompiled, and got errors.

    >> ...
    >>> The trouble is that now the code won't compile under JDK 1.5 because
    >>> RowId is a new class in 1.6 and doesn't exist in 1.5.
    >>>
    >>> So I appear to have an impossible situation: no way to make the code
    >>> compilable under 1.5 and 1.6 at the same time.
    >>>
    >>> What's the way out?

    >> I have ebeen thinking on similar problems related
    >> to cross-compilation. Although I have not actually
    >> tested it yet, I figure it *might* be possible to get a
    >> clean compile by specifying a -bootclasspath
    >> pointing to the 1.5 rt.jar, with the 1.6 rt.jar added
    >> to the standard classpath.
    >>

    >
    > What would that mean at runtime, though?
    >
    > Maybe I should just test this, but what if I leave the extra methods off
    > my class, compile it under 1.5, and then run it under 1.6? Does it blow
    > up when my class is loaded?


    Should only be a problem if those methods are invoked (you get a
    NoSuchMethodError). If you are running on 1.5, none of the other JDBC
    classes will know about the 1.6 methods, so they won't call them.

    I am surprised that Sun have chosen to add methods to an existing
    interface. I thought they were stricter on backwards compatibility than
    that. I was under the impression that the backwards compatibility
    argument was the reason that the clone() method has never been added to
    the Cloneable interface. This would potentially cause similar
    incompatibilities to the one that you are seeing, but in the case of
    Cloneable it would only affect classes that deserve to break.

    Dan.

    --
    Daniel Dyer
    http://www.uncommons.org
    Daniel Dyer, Dec 13, 2006
    #5
  6. Chris

    Chris Guest

    Andrew Thompson wrote:
    > Chris wrote:
    >
    >> What would that mean at runtime, though?
    >>
    >> Maybe I should just test this,

    >
    > Maybe you should.
    >
    >> ..but what if I leave the extra methods off
    >> my class, compile it under 1.5, and then run it under 1.6?

    >
    > Any code that can run successfully in 1.5, should work in
    > 1.6 (1.7, 1.8) - barring a JVM bug of some sort(, or reliance
    > on bugs that happen in 1.5).
    >
    >> ...Does it blow
    >> up when my class is loaded?

    >
    > No. Whay would you think that might pose a problem,
    > as opposed to the other way around (running 1.6 code,
    > written in the 1.6 class format - in 1.5)?
    >


    I just tested it, and code that compiles under 1.5 runs fine in 1.6.

    The reason I thought that there would be a problem is that at runtime,
    the system is going to load the 1.6 interface when I reference it, and
    then the 1.5 class that implements it. Clearly the 1.5 class will not
    meet the requirements of the interface. It doesn't appear that the JVM
    checks for this, though. The constraint that an interface imposes on an
    implementing class must be a compile-time only constraint.

    Nevertheless, that doesn't solve my problem, because the IDE (correctly)
    forces a recompile of everything when I switch JVM versions. So it still
    seems that it's impossible to write code that implements
    java.sql.ResultSet and compiles under both 1.5 and 1.6. This will make
    it hard to use 1.6 for testing or development.
    Chris, Dec 13, 2006
    #6
  7. Chris wrote:
    >
    > The trouble is that one of our classes implements the java.sql.ResultSet
    > interface, and they changed the interface to include more methods. For
    > example:


    > The trouble is that now the code won't compile under JDK 1.5 because
    > RowId is a new class in 1.6 and doesn't exist in 1.5.


    Welcome to JDBC interface changing hell.

    The easiest solution: compile with 1.5 bootclasses (or java.sql
    extracted from 1.5 and replacing 1.6 classes with -Xbootclasspath/p:).

    If you want to compile on both platforms I suggest three source
    directories: one directory containing common code (including an abstract
    implementation of ResultSet), one directory containing the small amount
    of 1.5 specific code and the last 1.6 code (using largely the same class
    names as the 1.5 code). For 1.5 builds compile with the first two on the
    sourcepath; for 1.6 use the first and last.


    So:


    In directory java:

    package xx.example;

    abstract class AbstractResultSet implements java.sql.ResultSet {
    ... constructors ...
    ... bulk of code ...
    }
    ....
    ResultSetImpl results = new ResultSetImpl(...);


    In directory java15:

    package xx.example;

    class ResultSetImpl extends AbstractResultSet {
    ... constructors ...
    }


    In directory java16:

    package xx.example;

    class ResultSetImpl extends AbstractResultSet {
    ... constructors ...
    public java.sql.RowId getRowId(int columnIndex) {
    throw new UnsupportedOperationException();
    }
    ... other JDBC 4.0 methods ...
    }

    Tom Hawtin
    Thomas Hawtin, Dec 13, 2006
    #7
  8. Chris wrote:
    .....
    > Nevertheless, that doesn't solve my problem, because the IDE (correctly)
    > forces a recompile of everything when I switch JVM versions.


    Sounds like a problem with your IDE.
    The -bootclasspath option of javac works
    just fine from the command line.

    Andrew T.
    Andrew Thompson, Dec 14, 2006
    #8
  9. Chris wrote:
    >
    > The reason I thought that there would be a problem is that at runtime,
    > the system is going to load the 1.6 interface when I reference it, and
    > then the 1.5 class that implements it. Clearly the 1.5 class will not
    > meet the requirements of the interface. It doesn't appear that the JVM
    > checks for this, though. The constraint that an interface imposes on an
    > implementing class must be a compile-time only constraint.


    The original specifications did not specify a precise outcome in this
    case (compiling and running a program does not mean it is correct, even
    in Java). IIRC, it was to allow the java.sql interfaces to evolve the
    led to the specs being tightened up. Previously, I believe, you could
    get a linkage error earlier, at the JVM's discretion.

    If you run 1.6 client on 1.6 with a 1.5 JDBC driver, you will get an
    AbstractMethodError for the new methods.

    If you somehow run a 1.6 client on 1.5, you will get a NoSuchMethodError
    for the new methods (because of improvements in javac defaults, you
    would need to have used -source and -target without -bootclasspath,
    which is daft).

    Tom Hawtin
    Thomas Hawtin, Dec 14, 2006
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ulf Meinhardt
    Replies:
    0
    Views:
    6,395
    Ulf Meinhardt
    Aug 10, 2006
  2. Jaggu
    Replies:
    3
    Views:
    965
    Nigel Wade
    Jan 8, 2007
  3. Roedy Green
    Replies:
    3
    Views:
    2,351
    Arne Vajhøj
    Aug 6, 2009
  4. Mike Schilling
    Replies:
    2
    Views:
    2,011
    Mike Schilling
    Sep 27, 2009
  5. Jochen Brenzlinger
    Replies:
    5
    Views:
    902
    Roedy Green
    Sep 2, 2011
Loading...

Share This Page