Skip to content

Commit

Permalink
Dramatically improve performance by skipping classloader
Browse files Browse the repository at this point in the history
  • Loading branch information
avantgardnerio committed Oct 31, 2018
1 parent 046958f commit 87e8564
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 15 deletions.
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ dependencies {
compile group: 'org.ow2.asm', name: 'asm', version: '4.0'
compile group: 'org.ow2.asm', name: 'asm-commons', version: '7.0'
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.7'
compile group: 'commons-io', name: 'commons-io', version: '2.6'

testCompile group: 'junit', name: 'junit', version: '4.12'
}
Expand Down
37 changes: 22 additions & 15 deletions src/main/kotlin/net/squarelabs/depends/Resolver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,19 @@ import net.squarelabs.depends.models.Artifact
import net.squarelabs.depends.models.Class
import net.squarelabs.depends.models.Invocation
import net.squarelabs.depends.models.Method
import org.apache.commons.io.FilenameUtils
import org.jboss.shrinkwrap.resolver.api.maven.Maven
import org.objectweb.asm.ClassReader
import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Opcodes
import org.objectweb.asm.commons.InstructionAdapter
import java.io.File
import java.io.FileInputStream
import java.io.InputStream
import java.net.URLClassLoader
import java.util.zip.ZipFile
import java.util.zip.ZipInputStream

var methodCount = 0
var invocationCount = 0
Expand All @@ -37,21 +42,25 @@ fun resolve(coordinate: String, state: State): Artifact {
}

fun classesFromFile(file: File): Map<String,Class> {
return URLClassLoader(arrayOf(file.toURL())).use { it ->
val cp = ClassPath.from(it)
val size = cp.topLevelClasses.size
val classes = mutableMapOf<String,Class>()
cp.topLevelClasses.forEachIndexed { index, clazz ->
val methods = methodsFromClass(clazz, it)
if (index % 1000 == 0) println("$methodCount methods and $invocationCount invocations class $index / $size is ${clazz.name}")
// assert(classes.get(clazz.name) == null) // TODO: handle duplicates /foo/bar/class vs /foo.bar/class
classes[clazz.name] = Class(clazz.name, methods)
val classes = mutableMapOf<String,Class>()
ZipFile(file).use { zipFile ->
zipFile.stream().forEach { entry ->
val ext = FilenameUtils.getExtension(entry.name)
if(ext == "class") {
val packageName = FilenameUtils.getPath(entry.name).replace("/", ".")
val className = FilenameUtils.getBaseName(entry.name)
val fqcn = "$packageName$className"
zipFile.getInputStream(entry).use { stream ->
val methods = methodsFromClass(stream)
classes[fqcn] = Class(fqcn, methods)
}
}
}
classes.toMap()
}
return classes.toMap()
}

fun methodsFromClass(clazz: ClassPath.ClassInfo, loader: URLClassLoader): Map<String, Method> {
fun methodsFromClass(stream: InputStream): Map<String, Method> {
val methods = mutableMapOf<String, Method>()
val cl = object : ClassVisitor(Opcodes.ASM7) {
override fun visitMethod(access: Int, methodName: String,
Expand All @@ -75,10 +84,8 @@ fun methodsFromClass(clazz: ClassPath.ClassInfo, loader: URLClassLoader): Map<St
}
}

loader.getResourceAsStream(clazz.resourceName).use { stream ->
val classReader = ClassReader(stream)
classReader.accept(cl, 0)
}
val classReader = ClassReader(stream)
classReader.accept(cl, 0)

return methods.toMap()
}

0 comments on commit 87e8564

Please sign in to comment.