Java Instrumentation + ASM + MultiMC

Discussion in 'Mod Development' started by FyberOptic, Jun 2, 2015.

  1. FyberOptic

    FyberOptic New Member

    I encountered an issue when trying to use Java Instrumentation to use ASM on LaunchWrapper while running under MultiMC, so I thought I'd leave a post to help anyone else who might have a similar problem. I realize it's not likely, since the only other mod I've ever seen that uses Instrumentation is Ugocraft, and it doesn't use ASM so the problem doesn't even affect it. But you never know what folks might be up to!

    In a nutshell, if you try to use ASM (or anything from an external library) in your Instrumentation class when executed under MultiMC, you'll crash from a class not found.

    The problem is in how MultiMC launches Minecraft. MultiMC is written in C++ but it uses a loader written in Java to bridge the gap. When you specify a javaagent in the Java command line arguments, your Instrumentation class will be loaded and executed before MultiMC's custom loader. The classpath to run Minecraft isn't set by MultiMC beforehand, instead it's passed through an input stream to the Java loader, which then inserts those libraries into the classpath before eventually executing the the main Minecraft entry point. If you're trying to use ASM in your Instrumentation class, then the library for it isn't specified on the classpath when the MultiMC loader is executed, and since your Instrumentation class is trying to execute before the loader sets up the classpath in its own way, then you crash from a class not found error. The vanilla launcher doesn't behave this way, so it presents an unexpected issue.

    You might think that the MultiMC dev could simply set the classpath before executing its Java loader and avoid the problem, but he told me that he specifically sets up the classpath the way he does to avoid unicode issues on the Java command line.

    To circumvent the issue, what you need to do is avoid doing anything in your Instrumentation class that uses an external library until the environment is in a predictable state. The easiest way to know when the classpath has been properly configured is when LaunchWrapper is being loaded. So in your class that implements ClassFileTransformer, just wait for any of the classes from LaunchWrapper to show up, and at that point you know you're good. You can then load a class that executes ASM functionality or anything from a library specified in the JSONs and it'll work as expected.

    In my case, I was trying to use ASM on LaunchWrapper itself to hook where it executes transformers, so I just wait until LaunchClassLoader shows up in my Instrumentation transformer method and then execute a static method in an entirely different class (one which hasn't been loaded yet) to transform it. Works like a charm.

    The MultiMC guys may implement direct support for Instrumentation later on, which would be cool.
     
    ljfa and lenscas like this.
  2. immibis

    immibis New Member

    Couldn't you alternatively bundle ASM into your instrumentation plugin?
     
  3. FyberOptic

    FyberOptic New Member

    I did initially but then I also needed access to a LaunchWrapper class and ended up with the same problem. I felt the better solution was to just wait until they're available.

    I never tried Magic Launcher, but I'll just assume that it behaves more like the vanilla one since it's also in Java.
     

Share This Page