Interface TransformableClassloader

All Known Implementing Classes:
MinestomRootClassLoader

@AvailableSince("4.0.0-a20231223") public interface TransformableClassloader
Interface that should be applied on implementations of ClassLoader to mark that they can be transformed via ASM Transformers.

This interface exists for abstraction reasons, as SLL's classloader classes will not exist in the minestom package forever - that is, the package in which they exist will be renamed with SLL 5.

When implementing your own classloader, you are encouraged to implement this interface for compatibility reasons.

Since:
4.0.0-a20231223
  • Method Details

    • addASMTransformer

      @Contract(pure=false, mutates="this") @AvailableSince("4.0.0-a20231223") void addASMTransformer(@NotNull @NotNull ASMTransformer transformer)
    • getASMTransformers

      @NotNull @Contract(pure=true, value="-> new") @AvailableSince("4.0.0-a20231223") @NotNull @Unmodifiable Collection<@NotNull ASMTransformer> getASMTransformers()
    • isThreadLoggingClassloadingFailures

      @Contract(pure=true) @AvailableSince("4.0.0-a20240730") boolean isThreadLoggingClassloadingFailures()
      Obtains whether the current thread should be logging classloading-related exceptions for this specific classloader. This may relate to class transformation issues, I/O issues, illegal bytecode among other potential causes. The reason SLL logs these kinds of issues by default is that at times the exceptions that are thrown by the classloader are completely absorbed by the caller. This very easily results in rather hard to trace issues as people will usually not expect a classloading failure as the cause of a bug. This is especially relevant in asynchronous environments where exception swallowing is already very likely in conjunction with faulty ASM Transformers resulting in either a transformation failure or illegal bytecode to be emitted.

      Regardless of this setting, the classloader will always rethrow the exception (or wrap it appropriately, attaching necessary debug info if applicable). By default this setting is set to true and is on a per-thread basis, that is the value is backed by a ThreadLocal and will thus have concurrency behaviours that align with those of ThreadLocal.

      Reasons why this setting may be disabled is either because failures are expected (as is the case in the micromixin test framework for example) or because the thrown exceptions are already being logged and no duplication should occur. Generally disabling logging of these issues should be temporary in nature only where it acutely applies.

      Returns:
      Whether the current thread should log classloading failures explicitly.
      Since:
      4.0.0-a20240730
    • setThreadLoggingClassloadingFailures

      @Contract(pure=false, value="_ -> this") @AvailableSince("4.0.0-a20240730") TransformableClassloader setThreadLoggingClassloadingFailures(boolean logFailures)
      Sets whether the current thread should be logging classloading-related exceptions for this specific classloader. This may relate to class transformation issues, I/O issues, illegal bytecode among other potential causes. The reason SLL logs these kinds of issues by default is that at times the exceptions that are thrown by the classloader are completely absorbed by the caller. This very easily results in rather hard to trace issues as people will usually not expect a classloading failure as the cause of a bug. This is especially relevant in asynchronous environments where exception swallowing is already very likely in conjunction with faulty ASM Transformers resulting in either a transformation failure or illegal bytecode to be emitted.

      Regardless of this setting, the classloader will always rethrow the exception (or wrap it appropriately, attaching necessary debug info if applicable). By default this setting is set to true and is on a per-thread basis, that is the value is backed by a ThreadLocal and will thus have concurrency behaviours that align with those of ThreadLocal.

      Reasons why this setting may be disabled is either because failures are expected (as is the case in the micromixin test framework for example) or because the thrown exceptions are already being logged and no duplication should occur. Generally disabling logging of these issues should be temporary in nature only where it acutely applies.

      Parameters:
      logFailures - Whether the current thread should log classloading failures explicitly.
      Returns:
      The current TransformableClassloader instance, for chaining.
      Since:
      4.0.0-a20240730
    • transformAndDefineClass

      @NotNull @Contract(pure=false) @CheckReturnValue @AvailableSince("4.0.0-a20231223") @NotNull Class<?> transformAndDefineClass(@NotNull @NotNull String className, @NotNull @NotNull RawClassData data)