Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug in Platform.getClassForName #5457

Closed
scabug opened this issue Feb 12, 2012 · 9 comments
Closed

Bug in Platform.getClassForName #5457

scabug opened this issue Feb 12, 2012 · 9 comments

Comments

@scabug
Copy link

scabug commented Feb 12, 2012

Platform.getClassForName fails to load a class if the code calling it is not compiled with the -optimize flag. It looks like a different classloader is used if the call occurs within the Platform object than when it is inlined. You can see difference if you compile the attached code w/o -optimize and compare the two stack traces.

@scabug
Copy link
Author

scabug commented Feb 12, 2012

Imported From: https://issues.scala-lang.org/browse/SI-5457?orig=1
Reporter: @eengbrec
Affected Versions: 2.9.1
Attachments:

  • TestCls.scala (created on Feb 12, 2012 6:42:49 PM UTC, 397 bytes)

@scabug
Copy link
Author

scabug commented Feb 14, 2012

@cvogt said:
I cannot reproduce this in Windows. Neither with 2.9.1 nor trunk. Can you try in Mac OS please?

Regardless if -optimize is set or not, I always get:

Foo
Foo
java.lang.ClassNotFoundException: sdf
        at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
        at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.scala$tools$nsc$util$ScalaClassLoader$$super$findClass(ScalaClassLoader.scala:88)
        at scala.tools.nsc.util.ScalaClassLoader$class.findClass(ScalaClassLoader.scala:44)
        at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.findClass(ScalaClassLoader.scala:88)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
        at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.scala$tools$nsc$util$ScalaClassLoader$$super$loadClass(ScalaClassLoader.scala:88)
        at scala.tools.nsc.util.ScalaClassLoader$class.loadClass(ScalaClassLoader.scala:50)
        at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.loadClass(ScalaClassLoader.scala:88)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:169)
        at TestClass$.main(TestCls.scala:16)
        at TestClass.main(TestCls.scala)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:78)
        at scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:24)
        at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:88)
        at scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:78)
        at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101)
        at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:33)
        at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:40)
        at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:56)
        at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:80)
        at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:89)
        at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)

@scabug
Copy link
Author

scabug commented Feb 14, 2012

@adriaanm said:

[adriaan@lampmac13 scala (topic/virtpatmat)]$ qsc -version
Scala compiler version v2.10.0-M1-0177-g39dd0f7924-2012-02-14 -- Copyright 2002-2011, LAMP/EPFL
[adriaan@lampmac13 scala (topic/virtpatmat)]$ qsc -optimize /Users/adriaan/Downloads/TestCls.scala 
[adriaan@lampmac13 scala (topic/virtpatmat)]$ qs TestClass
Foo
Foo
java.lang.ClassNotFoundException: sdf
	at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.scala$tools$nsc$util$ScalaClassLoader$$super$findClass(ScalaClassLoader.scala:159)
	at scala.tools.nsc.util.ScalaClassLoader$class.findClass(ScalaClassLoader.scala:57)
	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.findClass(ScalaClassLoader.scala:159)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.scala$tools$nsc$util$ScalaClassLoader$$super$loadClass(ScalaClassLoader.scala:159)
	at scala.tools.nsc.util.ScalaClassLoader$class.loadClass(ScalaClassLoader.scala:63)
	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.loadClass(ScalaClassLoader.scala:159)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:169)
	at TestClass$.main(TestCls.scala:16)
	at TestClass.main(TestCls.scala)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:90)
	at scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:38)
	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:159)
	at scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:90)
	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:159)
	at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:28)
	at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:45)
	at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:35)
	at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:45)
	at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:70)
	at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:92)
	at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:101)
	at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)

cleaning class files just in case, then without optimize -- different exception

[adriaan@lampmac13 scala (topic/virtpatmat)]$ rm /tmp/*.class
[adriaan@lampmac13 scala (topic/virtpatmat)]$ qs TestClass
No such file or class on classpath: TestClass

[adriaan@lampmac13 scala (topic/virtpatmat)]$ qsc /Users/adriaan/Downloads/TestCls.scala 
[adriaan@lampmac13 scala (topic/virtpatmat)]$ qs TestClass
java.lang.ClassNotFoundException: Foo
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:169)
	at scala.compat.Platform$.getClassForName(Platform.scala:104)
	at TestClass$.main(TestCls.scala:7)
	at TestClass.main(TestCls.scala)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:90)
	at scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:38)
	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:159)
	at scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:90)
	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:159)
	at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:28)
	at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:45)
	at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:35)
	at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:45)
	at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:70)
	at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:92)
	at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:101)
	at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
Foo
java.lang.ClassNotFoundException: sdf
	at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.scala$tools$nsc$util$ScalaClassLoader$$super$findClass(ScalaClassLoader.scala:159)
	at scala.tools.nsc.util.ScalaClassLoader$class.findClass(ScalaClassLoader.scala:57)
	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.findClass(ScalaClassLoader.scala:159)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.scala$tools$nsc$util$ScalaClassLoader$$super$loadClass(ScalaClassLoader.scala:159)
	at scala.tools.nsc.util.ScalaClassLoader$class.loadClass(ScalaClassLoader.scala:63)
	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.loadClass(ScalaClassLoader.scala:159)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:169)
	at TestClass$.main(TestCls.scala:16)
	at TestClass.main(TestCls.scala)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:90)
	at scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:38)
	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:159)
	at scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:90)
	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:159)
	at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:28)
	at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:45)
	at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:35)
	at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:45)
	at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:70)
	at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:92)
	at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:101)
	at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)

@scabug
Copy link
Author

scabug commented Feb 21, 2012

@VladUreche said:
Interesting: I can reproduce the bug running with scala, but running with java it always gives me:

$ java -cp .:$SCALA_PACK/lib/scala-library.jar TestClass
Foo
Foo
Exception in thread "main" java.lang.ClassNotFoundException: sdf
[...]

@scabug
Copy link
Author

scabug commented Feb 21, 2012

@VladUreche said:
Classloader issue. This testcase shows the problem clearly:

class Foo

object TestClass {
  def main(args: Array[String]) {

    try {
      val cls = java.lang.Class.forName("Foo")
      println(cls.getName)
    } catch {
      case e => println(e)
    }

    try {
      val cls = scala.compat.Platform.getClassForName("Foo")
      println(cls.getName)
    } catch {
      case e => println(e)
    }
  }
}
$ rm -f *.class; scalac TestCls.scala
$ scala TestClass
Foo
java.lang.ClassNotFoundException: Foo

Yes, you're not dreaming, it says "ClassNotFoundException" after if it found and loaded Foo!

@scabug
Copy link
Author

scabug commented Jun 11, 2012

@adriaanm said:
Eugene, could you apply your recently acquired classloader-fu?

@scabug
Copy link
Author

scabug commented Dec 9, 2012

@paulp said:
It's the runner's usage of the boot classloader for speed.

% scala3 TestClass
Foo
java.lang.ClassNotFoundException: Foo
% scala3 -nobootcp TestClass
Foo
Foo

The fact that it works under -optimise but fails without it highlights an interesting and heretofore unknown (at least, I've never heard anyone mention it) risk of inlining. If you inline code from one class into another class, and those classes wind up being loaded from different classloaders, you can change the meaning of the code. A call to Class.forName(name) will load from the classloader of the callee rather than the classloader of the caller.

This means that the one-argument form of Class.forName must never be inlined; or it must first be expanded to the three argument form. I will open a separate ticket about this.

@scabug
Copy link
Author

scabug commented Dec 9, 2012

@paulp said:
Opened #6789.

@SethTisue
Copy link
Member

unless I misunderstand, this is superseded by #6789

@SethTisue SethTisue removed this from the Backlog milestone Mar 3, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants