Plugin reloading/enabling

See, I guess I didn’t know that. If I knew how bad it was (low level) to run commands from Plugman, I wouldn’t have made this post. At the surface, Plugman just appears to work. But I can see if it’s not done properly, it can cause some serious issues.

1 Like

Personally I think, plugin developers should care about their dependencies and make sure these are available. The only problems I had with plugman were plugins trying to access unloaded classes (e.g. Plugin A trying to hook into vault, but then vault gets unloaded…)

1 Like

@Amaranth said the truth

Plugman only call the disable and enable method of a plugin …
Sponge have not such methods.

shared objects (static fields) are not resettet, classes are already loaded, …
That create a undefined state …

It’s look like it working, but it was a horrible illusion …

BUT

Most server owner does not want a plugin reload, they only want a config reload,
and for that plugman worked mostly …

What a reload is useful for:

  • load the config again from disk
  • clear caches

What a reload can not be:

  • replace a server restart
  • a clean reset of the plugin
3 Likes

I wrote a custom plugin for my server that was able to enable/disable individual plugins on my server. The plugin made sure it wouldn’t disable itself, so it was always running. To reload a plugin, I would just disable it, and then re-enable it. Seemed to work. Having something like this built in would be nice.

The part that isn’t so nice is the disabling of dependent plugins. From a user standpoint, even if a plugin depended on another, disabling it shouldn’t disable other plugins. That’s just weird and unexpected.

1 Like

The problem with reloading plugins/mods/extensions/etc. in most languages, Java included, is that ultimately a plugin will leave references to itself in the main application or in other plugins.

In Java, for example, plugin A might use B and get a class Apple from B. Upon reloading B, A still has a copy of Apple from B but it is the old version of the class from before the reload. Java does not see the two classes to be the same and you will encounter problems.

It also risks classloader leaks, where these references stick around for a long time and compound after every restart, so you end up with a memory leak.

If you are developing, I recommend running the server from within your IDE. If you are only making minor changes (not removing or adding methods), you can just “reload changed classes” and inject your changes into the running server without restarting or reloading anything. No (manual) compilation needed. Immediate effect.

4 Likes

Ah, this makes sense.

Then isn’t there a responsibility for the developer to make sure that plugin B is loaded anytime plugin A tries to do something with it? Otherwise yes, memory leaks would occur, but that’s up to the developer. If the developer wants to be stupid, let them. stuck_out_tongue

2 Likes

I think the only way to do it in a way that is safe at all would be to enforce a policy where plugins specify their dependencies, requiring each dependency to be loaded before each plugin is. When a plugin is (un|re)loaded, all its dependees would be too. In theory it seems simple, but enforcing it might be a pain. That said, there is of course some basic stuff that Sponge could do to minimize boilerplate, like keeping track of the plugin registering each event (no idea if this is the case already yet, haven’t looked at the code quite yet).

1 Like

For those who want to make a small change to a method or something similar during debugging, if you don’t run the server from your IDE you can directly utilize the technology that it does.

It is called HotSwap, and you can even set it up on a remote server to do remote debugging (inspecting the value of variables, performing a memory dump, hot swapping running classes, etc).

An idea. I understand that plugins can mess up the reload process, but that shouldn’t be an excuse to be lazy, making code to unload files from a classpath can take a few minutes to write. In the case of plugins messing the reload process up, add a parameter to the Plugin annotation that defaults to “reloadable=false”.

If I user has made their plugin reloadable they put “reloadable=true” in their @Plugin statement. Only plugins that are marked as reloadable would be reloaded.

At the minimum there needs to be a way to add additional plugins after startup. Let’s say I put plugin A and B in, and start the sever up, then I later decide to put plugin C in, I have to restart the entire server to load 1 additional file, which is as easy to do as using a class loader on the jar file and then calling a method on the plugin to allow it to initialize.

If you make plugins add that flag. It means that devs have written code to make that possible. I think it is more logic to make the reload like this than.

/pluginname reload

The way FML is written I don’t think it is possible. I never looked deep in to FML, but I am sure it remaps a lot of classes. As this probably doesn’t hurt for sponge plugins. Their is a possible change Forge Mods could have been reloaded using the same method. Also mixed plugins/mods. Will definitely crash the server using that.

1 Like

I really hope there is no reload command. All it does is spam errors and cause issues and memory leaks. Just restart it.

1 Like

I personally don’t care too much if the reload command is added, but if it was i would certainly not (and forbid my admins to) use it because of the severe safety issues it can cause.

This would still have the dependency problem. Let’s say WorldEdit has that “reloadable=true”-tag, and a portal plugin has WE as a dependency (for creating the portal areas) but has “reloadable=false”.
If a server owner would reload the plugins, WE would get reloaded, but the portal plugin would not, resulting in the very same dependency problem that was talked about all the time.

1 Like

And that would be where dynamic class loading would come in. Imagine the scenario below

@Dependency("WorldEdit")
static SpongePlugin worldEdit;

When this is loaded into the class loader and registered as a plugin with whatever form of a system bus they’re using they would associate that field with the plugin dependency. When the named plugin “WorldEdit” is reloaded the field would automatically be assigned the new value of the created instance of WorldEdit’s main class and marking the old instance for deletion by the GC.

From that point forward it’s expected that anyone who is going to have their project depend on another plugin should have proper code etiquette and properly manage there resources. If you wanted to make it even easier for people who aren’t properly managing their resources to avoid issues add an event to the event bus for PluginReloaded, in your plugin if the reloaded plugin is one of your dependencies then reform your instances. You can also have an event for prior to plugins being unloaded so extending plugins can save anything they need to before acquiring the new instance.

Its not hard to implement a system where it’s easy to avoid conflicts due to reloading a series of classes, and where you take care of memory leaks. Memory leaks only happen if you don’t properly manage the resources so unless the development team were to take shortcuts or be lazy if implementing this feature it would be nearly trivial. As a server developer myself I can tell you it’s annoying not only to the development team, but to the people playing on your server when you have a problem with a plugin, and you need to update that plugin to fix a small bug, or to reload an asset which couldn’t be opened (due to fore-say an IOException). Kicking everyone off the server multiple times (because who knows how many attempts it may take to fix the issue) is simply unacceptable when you have anything larger than 50 people online at any given time.

Bukkit did not implement the reload system well, so their version of the system was a fail and had major flaws. But hundreds of games use dynamic loading for mods and have no issues, because the devs know what they’re doing when implementing that ability. Just because Bukkit failed to make a reliable system, doesn’t mean one doesn’t exist or is impossible.

And so you’re imposing that plugins have the ability to delete themselves from the classpath and reload themselves again, if people are talking about issues with memory leaks and dependency issues that’s sure not going to fix anything.

1 Like

Totally not, I am imposing that if plugins have reload code, they should implement the commands by them self. If a server owner wants a plugin to be unloaded/loaded he will need to restart the server for that.

1 Like

What I’m stating about your comment thomas is you’re saying that if a plugin wants to allow reloading they implement it themselves.

This means that the developers of Sponge would need to allow the master class loader to be public to any plugins in-case that plugin wants to be able to access it to have their plugin be unloaded and loaded again into the classpath, which would be a major security flaw compared to adding support for it internally. I am talking about the form of reload and unload that physically removes and updates references to the actual class files as loaded by the JVM. I am not talking about simply reloading a config file or a basic asset, I’m talking in terms of being able to dynamically add and remove modules or plugins to the Sponge environment, including the idea of being able to update a plugin.

If I’m developing a plugin for a server that has 1,000 players on it, I do bug-testing before placing it on the main server. However with so many people there are guaranteed to be bugs you can’t find out in simple controlled testing and thus the server is bugged and the plugins need an update. A single plugin may need to be edited and fixed multiple times depending on it’s size. And your community of 1,000 would get furious with you having to constantly restart the entire server network every hour to fix a problem with a single plugin. Compared to having the server on adding the ability to unload and load that plugin.

The only excuse to not implement the system is exclusively that it’s either impossible or causes memory leaks, which are both false. It is very possible, and very easy, and the only time memory leaks will exist in the setup is if the devs are completely lazy and take stupid shortcuts to reduce the already minimal workload.

I have worked with Java for 12 years and I’ve been a developer for a server for about 2.5 years. One of my plugins I wrote was a plugin that allowed for Java add-ons to said plugin (RPG plugin, each class was written as its own plugin to the RPG plugin). The RPG plugin loaded jar files into the classpath, and unloaded and reloaded files into the classpath. The entire process took place in one Java file with only 483 lines of code and over the course of 4 months the only signs of a memory leak are some small memory leaks from Java or the server itself that exist with or without the RPG plugin. So what I’m saying are the excuses are just that, excuses. Just because Bukkit completely failed at making a reliable system doesn’t mean that it’s impossible to make one or that the system is bad when implemented correctly.

I understand what your saying, but the main problem is that sponge doesn’t own the class loader. The class loader is managed by forge. Every plugin that gets loaded also shows up like an effective mod. In order to make sponge have plug in reloading/enabling/disabling. Is see these options:

  • Making their own class loader. This will probably change a lot of the current work that has been done.
  • Making a Pull Request to forge to allow unloading mods. I am pretty sure that never will get in to forge.
  • Sponge manipulates the FML class loader. So it can unload/reload his plug-ins. I say hack
  • Making the class that loads sponge plugins and act like a piece holder. For example sponge has detected 18 plugins. It loads the 18 plugins in their piece holders. It also loads 5 extra piece-holders for other plugins. But set their state to disabled. When sponge reloads. It disables and removes all the plugin objects from the piece-holders and resets them. But this will probably cause memory leaks as well.

Maybe having 2 servers on the network. For example you work on server_2 and fix problems from server_1. When server_2 has it bugfixes complete. You simply set server_2 as active server and server_1 as non-active using a costum bungeecoord plugins (shouldn’t be that hard to make). When players re-spawn (from for example a mini-game server) bungeecoord makes them re-spawn on the new fixed server. When everyone is away from server_1, You simpley use a version control system to pull over the plugins/configs from server_2. And BAM server_1 acts now as your new fixed server.

I used this system with the tekkit lite modpack. Only when switching we had to switch the map folder as well. Because this server wasn’t a minigame server xD. Only I dit the bungeecoord shit manually than … . When server_1 went down it tried server_2 and than the lobby.

If you have the required experience by all means make a pull request and prove people wrong.

I’m sure people would love a properly implemented version of this if you are up to the task.

We can throw all sorts of fancy code snippets out but the absolute reality is that it just. Will. Not. Work. Case Closed. As we’ve already seen dependencies make this hard and in the case of plugins without a proper implementation (ie one by a new Dev) to handle a disable that would save configs, etc. would just drive me insane, if Sponge will be anything like Bukkit the forums will be full of inexperienced devs (like @Exstar) asking “OMG how I do this sponge is broken DDDDD:”.
BTW, I was joking about @Exstar.

2 Likes

@ButterDev wajow…

This topic was automatically closed after 2 days. New replies are no longer allowed.