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:
+1
-1
@@ -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()) {
|
||||
|
||||
+1
-1
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+16
-13
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user