Manage Apps failed to delete old plugin JAR

I’m developing a plugin with Atlassian Plugin SDK. On the SDK instance, hot deploy is working perfectly.

But if I try to upload the JAR file to a standalone Jira instance, once in a while it will fail to install it.

The log shows this exception, Jira is unable to delete the plugin JAR file:

Caused by: com.atlassian.plugin.PluginException: Unable to delete plugin file: C:\Program Files\Atlassian\Application Data\Jira\plugins\installed-plugins\plugin_10926289645992153076_ConfigMigration-1.0.0.jar
	at com.atlassian.plugin.loaders.DirectoryScanner.remove(
	at com.atlassian.plugin.loaders.ScanningPluginLoader.deleteDeploymentUnit(
	at com.atlassian.plugin.loaders.ScanningPluginLoader.removePlugin(
	at com.atlassian.plugin.loaders.ForwardingPluginLoader.removePlugin(
	at com.atlassian.plugin.loaders.PermissionCheckingPluginLoader.removePlugin(
	at com.atlassian.plugin.manager.DefaultPluginManager.lambda$unloadPlugin$21(
	at com.atlassian.plugin.manager.PluginTransactionContext.wrap(
	at com.atlassian.plugin.manager.DefaultPluginManager.unloadPlugin(
	at com.atlassian.plugin.manager.DefaultPluginManager.uninstallNoEvent(
	at com.atlassian.plugin.manager.DefaultPluginManager.lambda$updatePlugin$26(
	at com.atlassian.plugin.manager.PluginTransactionContext.wrap(
	at com.atlassian.plugin.manager.DefaultPluginManager.updatePlugin(
	at com.atlassian.plugin.manager.DefaultPluginManager.lambda$addPlugins$22(
	... 90 more

The plugin folder contains two JAR files, the older one is locked by Jira server itself and cannot be deleted:

The only way to resolve it is to stop Jira, delete the old JAR, and restart.

There are no other stacktraces in the log… nothing to indicate my plugin has failed to unload or anything like that.

Why is this happening and how can I prevent it from happening? I don’t want this to happen if I’m updating plugins on a production server.

I think it is the Manage Apps page trying to load all the plugins to get their information. If I wait for the page to finish loading, then the JAR file will be unlocked.

Turns out even if I waited for the Manage Apps to load fully, it can still fail to delete the old JAR file.