diff options
author | Lukas Rytz <lukas.rytz@gmail.com> | 2015-02-03 23:00:51 +0100 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@gmail.com> | 2015-02-07 07:45:55 +0100 |
commit | c283ce145a7b34f18deeeac5c3de2b102169e074 (patch) | |
tree | 70c31221356af895e3576c88792e3dae43386faa /test/files | |
parent | 357c15710d9db5d1a8a07cf91af7c24ae6ee884d (diff) | |
download | scala-c283ce145a7b34f18deeeac5c3de2b102169e074.tar.gz scala-c283ce145a7b34f18deeeac5c3de2b102169e074.tar.bz2 scala-c283ce145a7b34f18deeeac5c3de2b102169e074.zip |
Test java reflection on scala library / reflect / compiler jars
Run a number of Java reflection operations on all classes in
scala library / reflect / compiler.
The test is based on a draft by Jason.
Diffstat (limited to 'test/files')
-rw-r--r-- | test/files/jvm/innerClassEnclMethodJavaReflection.scala | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/test/files/jvm/innerClassEnclMethodJavaReflection.scala b/test/files/jvm/innerClassEnclMethodJavaReflection.scala new file mode 100644 index 0000000000..ee39cb43bf --- /dev/null +++ b/test/files/jvm/innerClassEnclMethodJavaReflection.scala @@ -0,0 +1,65 @@ +import scala.reflect.io._ +import java.net.URLClassLoader + +object Test extends App { + val jarsOrDirectories = Set("partest.lib", "partest.reflect", "partest.comp") map sys.props + + object AllowedMissingClass { + // Some classes in scala-compiler.jar have references to jline / ant classes, which seem to be + // not on the classpath. We just skip over those classes. + // PENDING: for now we also allow missing $anonfun classes: the optimizer may eliminate some closures + // that are refferred to in EnclosingClass attributes. SI-9136 + val allowedMissingPackages = Set("jline", "org.apache.tools.ant", "$anonfun") + + def ok(t: Throwable) = { + allowedMissingPackages.exists(p => t.getMessage.replace('/', '.').contains(p)) + } + + def unapply(t: Throwable): Option[Throwable] = t match { + case _: NoClassDefFoundError | _: ClassNotFoundException | _: TypeNotPresentException if ok(t) => Some(t) + case _ => None + } + } + + jarsOrDirectories foreach testClasses + + def testClasses(jarOrDirectory: String): Unit = { + val classPath = AbstractFile.getDirectory(new java.io.File(jarOrDirectory)) + + def flatten(f: AbstractFile): Iterator[AbstractFile] = + if (f.isClassContainer) f.iterator.flatMap(flatten) + else Iterator(f) + + val classFullNames = flatten(classPath).filter(_.hasExtension("class")).map(_.path.replace("/", ".").replaceAll(".class$", "")) + + // it seems that Class objects can only be GC'd together with their class loader + // (http://stackoverflow.com/questions/2433261/when-and-how-are-classes-garbage-collected-in-java) + // if we just use the same class loader for the entire test (Class.forName), we run out of PermGen + // even with that, we still neeed a PermGen of 90M or so, the default 64 is not enough. I tried + // using one class loader per 100 classes, but that didn't help, the classes didn't get GC'd. + val classLoader = new URLClassLoader(Array(classPath.toURL)) + + val faulty = new collection.mutable.ListBuffer[(String, Throwable)] + + def tryGetClass(name: String) = try { + Some[Class[_]](classLoader.loadClass(name)) + } catch { + case AllowedMissingClass(_) => None + } + + for (name <- classFullNames; cls <- tryGetClass(name)) { + try { + cls.getEnclosingMethod + cls.getEnclosingClass + cls.getEnclosingConstructor + cls.getDeclaredClasses + } catch { + case AllowedMissingClass(_) => + case t: Throwable => faulty += ((name, t)) + } + } + + if (faulty.nonEmpty) + println(faulty.toList mkString "\n") + } +} |