Need Java 8 to run program

A long time ago I wrote a Scala program. It was started automatically, but this did not happen anymore. While investigating I found out that the combination of Scala with my program needs Java 8, but at my system Java 11 is the default.
When setting the default to Java 8 it works, but with Java 11 I get:
java.lang.ClassNotFoundException: java.sql.Driver

This happens on the following statement:
Class.forName(“org.h2.Driver”)

What do I need to do to let my program run with Java 11?

How are you running your program? You need to ensure that the h2 jar is available on the classpath when starting your app.

I call the program with:
scala nl.decebal.quotes.Quotes

I do not think it is a classpath problem, because when:
java -version
gives:
openjdk version “11.0.7” 2020-04-14
it goes wrong, but when it gives:
openjdk version “1.8.0_222”
everything is OK.

Just a guess, but I’d try upgrading to a newer version of H2 and recompiling. This sounds like something changed in Java 11 that H2 is unhappy with; it wouldn’t surprise me if a newer version could cope better.

Could you post the relevant portion of your code where you load the SQL driver? I am not aware that h2 was part of the JDK distribution any time, so there probably is some branch where you load one SQL driver (Apache Derby / Java DB?) and h2 in some other case.

In any event, for this minimal example:

object Main extends App {
  println(Class.forName("org.h2.Driver"))
}

I get this error when running:

$ scala -J-showversion Check.scala
openjdk version "1.8.0_222"
OpenJDK Runtime Environment (build 1.8.0_222-ga)
OpenJDK 64-Bit Server VM (build 25.222-bga, mixed mode)

java.lang.ClassNotFoundException: org.h2.Driver
	at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:264)
	at Main$.delayedEndpoint$Main$1(Check.scala:4)
...

I think there must be something else at play which is why it works for you, apparently.

I don’t think it’s that H2 was part of the JDK distribution – my suspicion is that H2 has some sort of JDK dependency that changed between Java 8 and 11. Given that loading the H2 driver is causing a missing-class exception from the JDK, this strongly suggests a transitive-dependency problem…

I copied your code, but used the name CheckH2.scala. :wink:
With 1.8 I get:
scala -J-showversion CheckH2.scala
openjdk version “1.8.0_222”
OpenJDK Runtime Environment (build 1.8.0_222-8u222-b10-1~deb9u1-b10)
OpenJDK 64-Bit Server VM (build 25.222-b10, mixed mode)

class org.h2.Driver

I use the jar that I downloaded from https://h2database.com/h2-2019-03-13.zip in my classpath.

When I use java 11 I get:
scala -J-showversion CheckH2.scala
openjdk version “11.0.7” 2020-04-14
OpenJDK Runtime Environment (build 11.0.7+10-post-Debian-3deb10u1)
OpenJDK 64-Bit Server VM (build 11.0.7+10-post-Debian-3deb10u1, mixed mode, sharing)
java.lang.ClassNotFoundException: java.sql.Driver
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:550)
at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:458)
at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:452)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:451)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:315)
at Main$.delayedEndpoint$Main$1(CheckH2.scala:2)
at Main$delayedInit$body.apply(CheckH2.scala:1)
at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:76)
at scala.App$$anonfun$main$1.apply(App.scala:76)
at scala.collection.immutable.List.foreach(List.scala:392)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
at scala.App$class.main(App.scala:76)
at Main$.main(CheckH2.scala:1)
at Main.main(CheckH2.scala)
.…

Oh, so it’s not the h2 Driver class that is not found, but a different one. (it’s always important to post the complete stack trace, since that gives a clue as to what’s wrong here)

Java 9 introduced a module system. Running java --list-modules shows you the available modules.

Does it help when you run your program with --add-modules, e.g. scala -J--add-modules -Jjava.sql CheckH2.scala?

I am wondering, how do you set your classpath? You aren’t using any command line arguments?!

Well, it complains it doesn’t find java.sql.Driver. That class is part of the Java standard library. The only explanations I can think of are:

  • Your app is messing with class loading. Although, I don’t see any sign of that in the stack trace.

  • Your environment is not properly set up to find the Java standard library for OpenJDK 11 (usually, it’s in a file called rt.jar). In that case, a lot of code should fail with classes not found, but maybe trying to load H2 just happens to be the first thing that required the standard library, as some common classes are native to the JVM and don’t require loading.

Then I get:
java.lang.ClassNotFoundException: org.h2.driver
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:315)
at Main$.delayedEndpoint$Main$1(CheckH2.scala:2)
at Main$delayedInit$body.apply(CheckH2.scala:1)
at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:76)
at scala.App$$anonfun$main$1.apply(App.scala:76)
at scala.collection.immutable.List.foreach(List.scala:392)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
at scala.App$class.main(App.scala:76)
at Main$.main(CheckH2.scala:1)
at Main.main(CheckH2.scala)

I work in linux and have an environment variable CLASSPATH which contains :/var/lib/h2/jars/h2-current.jar:.

I do not have a rt.jar in my classpath. Maybe I need to do some things. I did not do really big things after going from 8 to 11.

That should be Driver with a capital D. Maybe that’s the problem.

I don’t think rt.jar is relevant here.

% scala -classpath h2-2019-03-13/h2/bin/h2-1.4.199.jar
[info] started at Fri May 22 11:55:46 PDT 2020
Welcome to Scala 2.13.2 (OpenJDK 64-Bit Server VM, Java 11.0.7).
Type in expressions for evaluation. Or try :help.

scala 2.13.2> Class.forName("org.h2.driver")
java.lang.ClassNotFoundException: org.h2.driver
...

scala 2.13.2> Class.forName("org.h2.Driver")
val res3: Class[_] = class org.h2.Driver

That was stupid of me. :’-(

It is very strange: interactively it works, but with running a program it does not.

I found a solution (for the moment):
JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64 scala -J-showversion CheckH2.scala

I should find out what is the real problem, but for the moment being my problem is solved.