- Mastering High Performance with Kotlin
- Igor Kucherenko
- 490字
- 2021-06-25 20:55:22
Resource leaks
An operating system has several resources that are limited in number, for instance, files or internet sockets. A resource leak is a situation where a computer program doesn't release the resources it has acquired. The most common example is a case where files have been opened but haven't been closed:
fun readFirstLine() : String {
val fileInputStream = FileInputStream("input.txt")
val inputStreamReader = InputStreamReader(fileInputStream)
val bufferedReader = BufferedReader(inputStreamReader)
return bufferedReader.readLine()
}
In the preceding code snippet, the input.txt file hasn't been closed after being acquired and used. InputStream is an abstract superclass of all classes representing an input stream of bytes. It implements the Closeable single-method interface with a close() method. The subclasses of InputStream override this method to provide the ability to release the input stream, and in our case the file, correctly. So a correct version of the readFirstLine() method would look like this:
fun readFirstLine() : String? {
var fileInputStream: FileInputStream? = null
var inputStreamReader: InputStreamReader? = null
var bufferedReader: BufferedReader? = null
return try {
fileInputStream = FileInputStream("input.txt")
inputStreamReader = InputStreamReader(fileInputStream)
bufferedReader = BufferedReader(inputStreamReader)
bufferedReader.readLine()
} catch (e: Exception) {
null
} finally {
fileInputStream?.close()
inputStreamReader?.close()
bufferedReader?.close()
}
}
It's important to close a stream inside a finally section because if you do it at the end of the try section and an exception is thrown, then you'll have a file handle leak.
In this example, we can see how the dispose pattern is used with the try-finally special language construction. It's a design pattern for resource management that assumes use of the method usually called close(), dispose(), or release() to free the resources once they aren't needed. But since Kotlin 1.2, thanks to extension functions, we can write something like this:
fun readFirstLine(): String? = File("input.txt")
.inputStream()
.bufferedReader()
.use { it.readLine() }
The use or useLines function executes the given block function on this resource and then closes it down correctly whether or not an exception is thrown.
The use and useLines functions return the result of the block, which is very convenient, especially in our case.
The source code of the use function also uses the try-finally construction to ensure resources will be closed:
public inline fun <T : Closeable?, R> T.use(block: (T) -> R): R {
var exception: Throwable? = null
try {
return block(this)
} catch (e: Throwable) {
exception = e
throw e
} finally {
when {
apiVersionIsAtLeast(1, 1, 0) -> this.closeFinally(exception)
this == null -> {}
exception == null -> close()
else ->
try {
close()
} catch (closeException: Throwable) {
// cause.addSuppressed(closeException) // ignored here
}
}
}
}
So scarce resources that have been acquired must be released. Otherwise, an application will suffer from a resource leak, for example, a file handle leak like the one we've just described. Another common reason for slow performance is a memory leak.
- Rust實(shí)戰(zhàn)
- Mastering Entity Framework
- Reactive Programming with Swift
- Neo4j Essentials
- Java應(yīng)用開發(fā)技術(shù)實(shí)例教程
- Nexus規(guī)模化Scrum框架
- Drupal 8 Module Development
- Python算法從菜鳥到達(dá)人
- Visual C#.NET Web應(yīng)用程序設(shè)計(jì)
- Python機(jī)器學(xué)習(xí)算法與應(yīng)用
- SQL Server 2016 從入門到實(shí)戰(zhàn)(視頻教學(xué)版)
- Training Systems Using Python Statistical Modeling
- Python+Office:輕松實(shí)現(xiàn)Python辦公自動(dòng)化
- Learning Concurrency in Python
- Mastering Embedded Linux Programming