mirror of
https://github.com/TermoraDev/termora.git
synced 2026-01-16 02:12:58 +08:00
fix: memory leaks
This commit is contained in:
@@ -0,0 +1,42 @@
|
|||||||
|
package app.termora.terminal.panel.vw
|
||||||
|
|
||||||
|
import app.termora.Disposable
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import javax.swing.JPanel
|
||||||
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
|
|
||||||
|
abstract class AutoRefreshPanel : JPanel(), Disposable {
|
||||||
|
companion object {
|
||||||
|
private val log = LoggerFactory.getLogger(AutoRefreshPanel::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected val coroutineScope = CoroutineScope(Dispatchers.IO)
|
||||||
|
|
||||||
|
protected abstract suspend fun refresh(isFirst: Boolean)
|
||||||
|
|
||||||
|
init {
|
||||||
|
coroutineScope.launch {
|
||||||
|
var isFirst = true
|
||||||
|
while (coroutineScope.isActive) {
|
||||||
|
try {
|
||||||
|
refresh(isFirst)
|
||||||
|
isFirst = false
|
||||||
|
} catch (e: Exception) {
|
||||||
|
if (log.isErrorEnabled) {
|
||||||
|
log.error(e.message, e)
|
||||||
|
}
|
||||||
|
if (isFirst) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
delay(1000.milliseconds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
coroutineScope.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
package app.termora.terminal.panel.vw
|
package app.termora.terminal.panel.vw
|
||||||
|
|
||||||
import app.termora.I18n
|
import app.termora.*
|
||||||
import app.termora.Icons
|
|
||||||
import app.termora.SSHTerminalTab
|
|
||||||
import app.termora.SshClients
|
|
||||||
import com.formdev.flatlaf.extras.FlatSVGIcon
|
import com.formdev.flatlaf.extras.FlatSVGIcon
|
||||||
import com.jgoodies.forms.builder.FormBuilder
|
import com.jgoodies.forms.builder.FormBuilder
|
||||||
import com.jgoodies.forms.layout.FormLayout
|
import com.jgoodies.forms.layout.FormLayout
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
import kotlinx.coroutines.swing.Swing
|
import kotlinx.coroutines.swing.Swing
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import org.apache.commons.lang3.StringUtils
|
import org.apache.commons.lang3.StringUtils
|
||||||
import org.jdesktop.swingx.JXBusyLabel
|
import org.jdesktop.swingx.JXBusyLabel
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
@@ -22,7 +21,6 @@ import java.io.StringReader
|
|||||||
import javax.swing.*
|
import javax.swing.*
|
||||||
import javax.xml.parsers.DocumentBuilderFactory
|
import javax.xml.parsers.DocumentBuilderFactory
|
||||||
import javax.xml.xpath.XPathFactory
|
import javax.xml.xpath.XPathFactory
|
||||||
import kotlin.time.Duration.Companion.milliseconds
|
|
||||||
|
|
||||||
class NvidiaSMIVisualWindow(tab: SSHTerminalTab, visualWindowManager: VisualWindowManager) :
|
class NvidiaSMIVisualWindow(tab: SSHTerminalTab, visualWindowManager: VisualWindowManager) :
|
||||||
SSHVisualWindow(tab, "NVIDIA-SMI", visualWindowManager) {
|
SSHVisualWindow(tab, "NVIDIA-SMI", visualWindowManager) {
|
||||||
@@ -79,6 +77,8 @@ class NvidiaSMIVisualWindow(tab: SSHTerminalTab, visualWindowManager: VisualWind
|
|||||||
percentageBtn.icon = if (isPercentage) Icons.text else Icons.percentage
|
percentageBtn.icon = if (isPercentage) Icons.text else Icons.percentage
|
||||||
nvidiaSMIPanel.refreshPanel()
|
nvidiaSMIPanel.refreshPanel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Disposer.register(this, nvidiaSMIPanel)
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class GPU(
|
private data class GPU(
|
||||||
@@ -183,8 +183,7 @@ class NvidiaSMIVisualWindow(tab: SSHTerminalTab, visualWindowManager: VisualWind
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class NvidiaSMIPanel : JPanel(BorderLayout()) {
|
private inner class NvidiaSMIPanel : AutoRefreshPanel() {
|
||||||
private val coroutineScope = CoroutineScope(Dispatchers.IO)
|
|
||||||
|
|
||||||
private val xPath by lazy { XPathFactory.newInstance().newXPath() }
|
private val xPath by lazy { XPathFactory.newInstance().newXPath() }
|
||||||
private val db by lazy {
|
private val db by lazy {
|
||||||
@@ -224,6 +223,8 @@ class NvidiaSMIVisualWindow(tab: SSHTerminalTab, visualWindowManager: VisualWind
|
|||||||
|
|
||||||
private fun initViews() {
|
private fun initViews() {
|
||||||
|
|
||||||
|
layout = BorderLayout()
|
||||||
|
|
||||||
add(
|
add(
|
||||||
FormBuilder.create().debug(false)
|
FormBuilder.create().debug(false)
|
||||||
.layout(
|
.layout(
|
||||||
@@ -253,27 +254,11 @@ class NvidiaSMIVisualWindow(tab: SSHTerminalTab, visualWindowManager: VisualWind
|
|||||||
|
|
||||||
|
|
||||||
private fun initEvents() {
|
private fun initEvents() {
|
||||||
coroutineScope.launch {
|
|
||||||
|
|
||||||
// 首次刷新
|
|
||||||
refresh(true)
|
|
||||||
|
|
||||||
while (coroutineScope.isActive) {
|
|
||||||
delay(1000.milliseconds)
|
|
||||||
|
|
||||||
try {
|
|
||||||
refresh()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
if (log.isErrorEnabled) {
|
|
||||||
log.error(e.message, e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private suspend fun refresh(isFirst: Boolean = false) {
|
override suspend fun refresh(isFirst: Boolean) {
|
||||||
val session = tab.getData(SSHTerminalTab.SSHSession) ?: return
|
val session = tab.getData(SSHTerminalTab.SSHSession) ?: return
|
||||||
|
|
||||||
val doc = try {
|
val doc = try {
|
||||||
@@ -347,7 +332,6 @@ class NvidiaSMIVisualWindow(tab: SSHTerminalTab, visualWindowManager: VisualWind
|
|||||||
refreshPanel()
|
refreshPanel()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initPanel() {
|
private fun initPanel() {
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ package app.termora.terminal.panel.vw
|
|||||||
import app.termora.*
|
import app.termora.*
|
||||||
import com.jgoodies.forms.builder.FormBuilder
|
import com.jgoodies.forms.builder.FormBuilder
|
||||||
import com.jgoodies.forms.layout.FormLayout
|
import com.jgoodies.forms.layout.FormLayout
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.swing.Swing
|
import kotlinx.coroutines.swing.Swing
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import org.apache.commons.lang3.StringUtils
|
import org.apache.commons.lang3.StringUtils
|
||||||
import org.apache.sshd.client.session.ClientSession
|
import org.apache.sshd.client.session.ClientSession
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
@@ -12,7 +13,6 @@ import java.awt.BorderLayout
|
|||||||
import javax.swing.*
|
import javax.swing.*
|
||||||
import javax.swing.table.DefaultTableCellRenderer
|
import javax.swing.table.DefaultTableCellRenderer
|
||||||
import javax.swing.table.DefaultTableModel
|
import javax.swing.table.DefaultTableModel
|
||||||
import kotlin.time.Duration.Companion.milliseconds
|
|
||||||
|
|
||||||
|
|
||||||
class SystemInformationVisualWindow(tab: SSHTerminalTab, visualWindowManager: VisualWindowManager) :
|
class SystemInformationVisualWindow(tab: SSHTerminalTab, visualWindowManager: VisualWindowManager) :
|
||||||
@@ -40,9 +40,8 @@ class SystemInformationVisualWindow(tab: SSHTerminalTab, visualWindowManager: Vi
|
|||||||
Disposer.register(this, systemInformationPanel)
|
Disposer.register(this, systemInformationPanel)
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class SystemInformationPanel : JPanel(BorderLayout()), Disposable {
|
private inner class SystemInformationPanel : AutoRefreshPanel() {
|
||||||
|
|
||||||
private val coroutineScope = CoroutineScope(Dispatchers.IO)
|
|
||||||
|
|
||||||
private val cpuProgressBar = SmartProgressBar()
|
private val cpuProgressBar = SmartProgressBar()
|
||||||
private val memoryProgressBar = SmartProgressBar()
|
private val memoryProgressBar = SmartProgressBar()
|
||||||
@@ -63,6 +62,7 @@ class SystemInformationVisualWindow(tab: SSHTerminalTab, visualWindowManager: Vi
|
|||||||
|
|
||||||
|
|
||||||
private fun initViews() {
|
private fun initViews() {
|
||||||
|
layout = BorderLayout()
|
||||||
add(createPanel(), BorderLayout.CENTER)
|
add(createPanel(), BorderLayout.CENTER)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,22 +109,10 @@ class SystemInformationVisualWindow(tab: SSHTerminalTab, visualWindowManager: Vi
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun initEvents() {
|
private fun initEvents() {
|
||||||
coroutineScope.launch {
|
|
||||||
while (coroutineScope.isActive) {
|
|
||||||
try {
|
|
||||||
refresh()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
if (log.isErrorEnabled) {
|
|
||||||
log.error(e.message, e)
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
delay(1000.milliseconds)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun refresh() {
|
override suspend fun refresh(isFirst: Boolean) {
|
||||||
val session = tab.getData(SSHTerminalTab.SSHSession) ?: return
|
val session = tab.getData(SSHTerminalTab.SSHSession) ?: return
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -144,7 +132,6 @@ class SystemInformationVisualWindow(tab: SSHTerminalTab, visualWindowManager: Vi
|
|||||||
log.error("refreshDisk", e)
|
log.error("refreshDisk", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun refreshCPUAndMem(session: ClientSession) {
|
private suspend fun refreshCPUAndMem(session: ClientSession) {
|
||||||
@@ -290,10 +277,6 @@ class SystemInformationVisualWindow(tab: SSHTerminalTab, visualWindowManager: Vi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispose() {
|
|
||||||
coroutineScope.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class Mem(
|
private data class Mem(
|
||||||
|
|||||||
Reference in New Issue
Block a user