mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-11-05 18:39:40 +01:00
Print more useful debug message when a LinkageError is thrown due to bad SLF4J classloading
This is a longstanding issue, mostly caused by plugins with bad Maven shade configurations. https://github.com/lucko/LuckPerms/issues?q=slf4j
This commit is contained in:
parent
2839c36ea2
commit
ec7994a561
@ -39,6 +39,7 @@ import org.bukkit.Server;
|
|||||||
import org.bukkit.command.ConsoleCommandSender;
|
import org.bukkit.command.ConsoleCommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@ -268,6 +269,14 @@ public class LPBukkitBootstrap extends JavaPlugin implements LuckPermsBootstrap
|
|||||||
return player != null && player.isOnline();
|
return player != null && player.isOnline();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable String identifyClassLoader(ClassLoader classLoader) {
|
||||||
|
if (classLoader instanceof org.bukkit.plugin.java.PluginClassLoader) {
|
||||||
|
return ((org.bukkit.plugin.java.PluginClassLoader) classLoader).getPlugin().getName();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean checkIncompatibleVersion() {
|
private static boolean checkIncompatibleVersion() {
|
||||||
try {
|
try {
|
||||||
Class.forName("com.google.gson.JsonElement");
|
Class.forName("com.google.gson.JsonElement");
|
||||||
|
@ -36,6 +36,9 @@ import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
|||||||
import net.luckperms.api.platform.Platform;
|
import net.luckperms.api.platform.Platform;
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
import net.md_5.bungee.api.plugin.Plugin;
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
|
import net.md_5.bungee.api.plugin.PluginDescription;
|
||||||
|
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@ -260,6 +263,16 @@ public class LPBungeeBootstrap extends Plugin implements LuckPermsBootstrap {
|
|||||||
return getProxy().getPlayer(uniqueId) != null;
|
return getProxy().getPlayer(uniqueId) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable String identifyClassLoader(ClassLoader classLoader) throws Exception {
|
||||||
|
Class<?> pluginClassLoader = Class.forName("net.md_5.bungee.api.plugin.PluginClassloader");
|
||||||
|
if (pluginClassLoader.isInstance(classLoader)) {
|
||||||
|
PluginDescription desc = (PluginDescription) pluginClassLoader.getDeclaredField("desc").get(classLoader);
|
||||||
|
return desc.getName();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean checkIncompatibleVersion() {
|
private static boolean checkIncompatibleVersion() {
|
||||||
try {
|
try {
|
||||||
Class<?> aClass = Class.forName("com.google.gson.internal.bind.TreeTypeAdapter");
|
Class<?> aClass = Class.forName("com.google.gson.internal.bind.TreeTypeAdapter");
|
||||||
|
@ -214,4 +214,17 @@ public interface LuckPermsBootstrap {
|
|||||||
*/
|
*/
|
||||||
boolean isPlayerOnline(UUID uniqueId);
|
boolean isPlayerOnline(UUID uniqueId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to identify the plugin behind the given classloader.
|
||||||
|
*
|
||||||
|
* <p>Used for giving more helpful log messages when things break.</p>
|
||||||
|
*
|
||||||
|
* @param classLoader the classloader to identify
|
||||||
|
* @return the name of the classloader source
|
||||||
|
* @throws Exception anything
|
||||||
|
*/
|
||||||
|
default @Nullable String identifyClassLoader(ClassLoader classLoader) throws Exception {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@ public class SqlStorage implements StorageImplementation {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init() throws Exception {
|
public void init() throws Exception {
|
||||||
this.connectionFactory.init();
|
this.connectionFactory.init(this.plugin);
|
||||||
|
|
||||||
boolean tableExists;
|
boolean tableExists;
|
||||||
try (Connection c = this.connectionFactory.getConnection()) {
|
try (Connection c = this.connectionFactory.getConnection()) {
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.common.storage.implementation.sql.connection;
|
package me.lucko.luckperms.common.storage.implementation.sql.connection;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -35,7 +37,7 @@ public interface ConnectionFactory {
|
|||||||
|
|
||||||
String getImplementationName();
|
String getImplementationName();
|
||||||
|
|
||||||
void init();
|
void init(LuckPermsPlugin plugin);
|
||||||
|
|
||||||
void shutdown() throws Exception;
|
void shutdown() throws Exception;
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.common.storage.implementation.sql.connection.file;
|
package me.lucko.luckperms.common.storage.implementation.sql.connection.file;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
import me.lucko.luckperms.common.storage.implementation.sql.connection.ConnectionFactory;
|
import me.lucko.luckperms.common.storage.implementation.sql.connection.ConnectionFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -44,7 +45,7 @@ abstract class FlatfileConnectionFactory implements ConnectionFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init() {
|
public void init(LuckPermsPlugin plugin) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,9 +25,12 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.common.storage.implementation.sql.connection.hikari;
|
package me.lucko.luckperms.common.storage.implementation.sql.connection.hikari;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.zaxxer.hikari.HikariConfig;
|
import com.zaxxer.hikari.HikariConfig;
|
||||||
import com.zaxxer.hikari.HikariDataSource;
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
|
import me.lucko.luckperms.common.plugin.logging.PluginLogger;
|
||||||
import me.lucko.luckperms.common.storage.implementation.sql.connection.ConnectionFactory;
|
import me.lucko.luckperms.common.storage.implementation.sql.connection.ConnectionFactory;
|
||||||
import me.lucko.luckperms.common.storage.misc.StorageCredentials;
|
import me.lucko.luckperms.common.storage.misc.StorageCredentials;
|
||||||
|
|
||||||
@ -36,6 +39,7 @@ import java.sql.SQLException;
|
|||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@ -73,8 +77,17 @@ public abstract class HikariConnectionFactory implements ConnectionFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init() {
|
public void init(LuckPermsPlugin plugin) {
|
||||||
HikariConfig config = new HikariConfig();
|
HikariConfig config;
|
||||||
|
try {
|
||||||
|
config = new HikariConfig();
|
||||||
|
} catch (LinkageError e) {
|
||||||
|
// dumb plugins seem to keep doing stupid stuff with shading of SLF4J and Log4J.
|
||||||
|
// detect this and print a more useful error message.
|
||||||
|
handleLinkageError(e, plugin);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
config.setPoolName("luckperms-hikari");
|
config.setPoolName("luckperms-hikari");
|
||||||
|
|
||||||
appendConfigurationInfo(config);
|
appendConfigurationInfo(config);
|
||||||
@ -141,4 +154,38 @@ public abstract class HikariConnectionFactory implements ConnectionFactory {
|
|||||||
}
|
}
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void handleLinkageError(LinkageError linkageError, LuckPermsPlugin plugin) {
|
||||||
|
List<String> noteworthyClasses = ImmutableList.of(
|
||||||
|
"org.slf4j.LoggerFactory",
|
||||||
|
"org.slf4j.ILoggerFactory",
|
||||||
|
"org.apache.logging.slf4j.Log4jLoggerFactory",
|
||||||
|
"org.apache.logging.log4j.spi.LoggerContext",
|
||||||
|
"org.apache.logging.log4j.spi.AbstractLoggerAdapter",
|
||||||
|
"org.slf4j.impl.StaticLoggerBinder"
|
||||||
|
);
|
||||||
|
|
||||||
|
PluginLogger logger = plugin.getLogger();
|
||||||
|
logger.warn("A " + linkageError.getClass().getSimpleName() + " has occurred whilst initialising Hikari. This is likely due to classloading conflicts between other plugins.");
|
||||||
|
logger.warn("Please check for other plugins below (and try loading LuckPerms without them installed) before reporting the issue.");
|
||||||
|
|
||||||
|
for (String className : noteworthyClasses) {
|
||||||
|
Class<?> clazz;
|
||||||
|
try {
|
||||||
|
clazz = Class.forName(className);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassLoader loader = clazz.getClassLoader();
|
||||||
|
String loaderName;
|
||||||
|
try {
|
||||||
|
loaderName = plugin.getBootstrap().identifyClassLoader(loader) + " (" + loader.toString() + ")";
|
||||||
|
} catch (Exception e) {
|
||||||
|
loaderName = loader.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.warn("Class " + className + " has been loaded by: " + loaderName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user