Fix multiple resource leaks by closing InputStream instances

The main fix is in BuiltInsPackageFragment, the rest is the improvement of
other usages of getResourceAsStream

 #KT-11433 Fixed
This commit is contained in:
Alexander Udalov
2016-03-29 13:20:14 +03:00
parent 8316953259
commit 0ea3b4ade4
6 changed files with 32 additions and 34 deletions
@@ -25,7 +25,7 @@ class RuntimePackagePartProvider(private val classLoader: ClassLoader) : Package
fun registerModule(moduleName: String) {
val mapping = try {
classLoader.getResourceAsStream("META-INF/$moduleName.${ModuleMapping.MAPPING_FILE_EXT}")?.let { stream ->
classLoader.getResourceAsStream("META-INF/$moduleName.${ModuleMapping.MAPPING_FILE_EXT}")?.use { stream ->
ModuleMapping.create(stream.readBytes())
}
}
@@ -31,8 +31,7 @@ class BuiltInsPackageFragment(
module: ModuleDescriptor,
loadResource: (path: String) -> InputStream?
) : DeserializedPackageFragment(fqName, storageManager, module, loadResource) {
private val proto = run {
val stream = loadResourceSure(BuiltInSerializerProtocol.getBuiltInsFilePath(fqName))
private val proto = loadResourceSure(BuiltInSerializerProtocol.getBuiltInsFilePath(fqName)).use { stream ->
val version = BuiltInsBinaryVersion.readFrom(stream)
if (!version.isCompatible()) {
@@ -30,7 +30,7 @@ abstract class DeserializedPackageFragment(
fqName: FqName,
protected val storageManager: StorageManager,
module: ModuleDescriptor,
protected val loadResource: (path: String) -> InputStream?
private val loadResource: (path: String) -> InputStream?
) : PackageFragmentDescriptorImpl(module, fqName) {
// component dependency cycle
@set:Inject
@@ -37,21 +37,20 @@ fun buildTestSuite(
val suite = TestSuite()
val ownerClass = TestData::class.java
val inputStream = ownerClass.classLoader!!.getResourceAsStream(ownerClass.getInternalName() + ".class")!!
ClassReader(inputStream).accept(object : ClassVisitor(ASM5) {
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?): MethodVisitor? {
return object : MethodNode(ASM5, access, name, desc, signature, exceptions) {
override fun visitEnd() {
val testCase = buildTestCase(ownerClass, this, create)
if (testCase != null) {
suite.addTest(testCase)
ownerClass.classLoader!!.getResourceAsStream(ownerClass.getInternalName() + ".class")!!.use { inputStream ->
ClassReader(inputStream).accept(object : ClassVisitor(ASM5) {
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?): MethodVisitor? {
return object : MethodNode(ASM5, access, name, desc, signature, exceptions) {
override fun visitEnd() {
val testCase = buildTestCase(ownerClass, this, create)
if (testCase != null) {
suite.addTest(testCase)
}
}
}
}
}
}, 0)
}, 0)
}
return suite
}
@@ -78,11 +78,8 @@ private class ClassBytes(val name: String) {
val inputStream = this.javaClass.classLoader.getResourceAsStream(name.replace('.', '/') + ".class")
?: throw EvaluateException("Couldn't find $name class in current class loader")
try {
inputStream.readBytes()
}
finally {
inputStream.close()
inputStream.use {
it.readBytes()
}
}
}
@@ -33,21 +33,24 @@ class KotlinJavascriptPackageFragment(
loadResource: (path: String) -> InputStream?
) : DeserializedPackageFragment(fqName, storageManager, module, loadResource) {
private val nameResolver =
NameResolverImpl.read(loadResourceSure(KotlinJavascriptSerializedResourcePaths.getStringTableFilePath(fqName)))
loadResourceSure(KotlinJavascriptSerializedResourcePaths.getStringTableFilePath(fqName)).use { stream ->
NameResolverImpl.read(stream)
}
override val classDataFinder = KotlinJavascriptClassDataFinder(nameResolver, loadResource)
override fun computeMemberScope(): DeserializedPackageMemberScope {
val packageStream = loadResourceSure(KotlinJavascriptSerializedResourcePaths.getPackageFilePath(fqName))
val packageProto = ProtoBuf.Package.parseFrom(packageStream, JsSerializerProtocol.extensionRegistry)
return DeserializedPackageMemberScope(
this, packageProto, nameResolver, packagePartSource = null, components = components, classNames = { loadClassNames() }
)
}
override fun computeMemberScope(): DeserializedPackageMemberScope =
loadResourceSure(KotlinJavascriptSerializedResourcePaths.getPackageFilePath(fqName)).use { packageStream ->
val packageProto = ProtoBuf.Package.parseFrom(packageStream, JsSerializerProtocol.extensionRegistry)
DeserializedPackageMemberScope(
this, packageProto, nameResolver, packagePartSource = null, components = components,
classNames = { loadClassNames() }
)
}
private fun loadClassNames(): Collection<Name> {
val classesStream = loadResourceSure(KotlinJavascriptSerializedResourcePaths.getClassesInPackageFilePath(fqName))
val classesProto = JsProtoBuf.Classes.parseFrom(classesStream, JsSerializerProtocol.extensionRegistry)
return classesProto.classNameList?.map { id -> nameResolver.getName(id) } ?: listOf()
}
private fun loadClassNames(): Collection<Name> =
loadResourceSure(KotlinJavascriptSerializedResourcePaths.getClassesInPackageFilePath(fqName)).use { classesStream ->
val classesProto = JsProtoBuf.Classes.parseFrom(classesStream, JsSerializerProtocol.extensionRegistry)
classesProto.classNameList?.map { id -> nameResolver.getName(id) } ?: listOf()
}
}