Table of Contents

Exporting and Dumping Mixin Targets

Exporting a Transformed Class

When debugging mixins, it's useful to be able to see the finalized classes with your changes and injects inserted. Mixin provides a flag that allows for this:

-Dmixin.debug.export=true

This should be placed in your VM options. Once your classes have been loaded, they will appear in \run\.mixin.out

Only Exporting Required Classes

Dumping every mixined class can be useful, but is often unnecessary and does slow down minecraft a bit. Mixin provides a convenient annotation for applying debug features to individual mixins:

@Debug(export = true) // Enables exporting for the targets of this mixin
@Mixin(...)
public class MyMixin {
    // Mixin code here
}

Dumping on Failure

In some cases, you may want to be able to inspect a target class upon Mixin failing and likely throwing a crash. Mixin provides an additional flag for this:

-Dmixin.dumpTargetOnFailure=true

Adding this to your VM options similarly to the export flag will dump the class as it was just as Mixin failed the injection. This can be particularly useful if the cause of the error cannot be understood from the errors, target code and Mixin as they are in the development environment.

Dumping will place the dumped classes to the same filepath as it would for a regular export.

Once you have an exported Mixin class, you should look for @MixinMerged annotated members, which represent the members added by Mixins. Injector handlers, the methods annotated by injector annotations, are generally at the very bottom of the exported class, and have “mangled” names. Meaning that, to ensure their names do not clash with any other injector, their names are procedurally modified by Mixin to be unique.

Reading Mangled Names

The mangled names, on Fabric Mixin, follow the structure of <injector type>$<session id>$<modid>$<original handler method name>(<parameters>).
The following table can be used to match the injector type prefix to the corresponding annotation:

Injector Annotation Mangled Prefix
Base Mixin
@Inject handler
@ModifyArg modify
@ModifyArgs args
@ModifyConstant constant
@ModifyVariable localvar
@Redirect redirect
MixinExtras
@ModifyExpressionValue modifyExpressionValue
@ModifyReceiver modifyReceiver
@ModifyReturnValue modifyReturnValue
@WrapWithCondition wrapWithCondition
@WrapOperation wrapOperation

Annotations on Merged Members

On top of being mangled, the handler is also annotated to provide additional information about the injector used. The handler will keep all of its @Expression and @Definition annotations if it used MixinExtras Expressions. When not using the Mixin Annotation Processor (off by default in latest Loom versions), the @Definitions will be remapped rather than using a refmap. This could be used to detect Loom failing to remap certain elements in the target method when dumping on failure.

Outside of expression annotations, the handler will be decorated with @MixinMerged, which is formatted as follows:

@MixinMerged(
    mixin = "<path to Mixin class>",
    priority = <Mixin class priority>,
    sessionId = "<session ID>"
)

(Formatting not necessarily consistent between decompilers)

This also applies to most merged members, though other annotations may be present depending on the member, such as @Unique for unique fields.

An example @MixinMerged could look like:

@MixinMerged(
    mixin = "net.fabricmc.fabric.mixin.resource.loader.MinecraftServerMixin",
    priority = 1000,
    sessionId = "f0f95788-8e61-4d03-8398-87e419457a83"
)

Using the mangled name and the @MixinMerged annotation's information, it is possible to distinguish which injector you wish to debug, and then look for usages of the mangled handler name in the class.

Notes

At what point are classes exported

Mixins are applied relative to when the target class is loaded. As such, classes may be transformed and exported at any point between the game starting and an in-game world loading. If a class is not being exported at all without errors, make sure your test run goes as far as world loading.

''@Debug'' persists in production environments

When using the @Debug annotation, remember that if you keep its export value to true, it will still export even when the mod is built into a jar to potentially be published. This could cause unintended and unnecessary behavior for your players, so remember to turn the @Debug annotation's exporting to false before any player-oriented jar is made.