Search code examples
javaproguardminecraftreflections

Why does invoke not work when using proguard obfuscation


I have a Fabric 1.17.1 (Java 16) mod for Minecraft that I am trying to obfuscate. Included with this mod is my event system that handles all the events for my mod. This event system uses the invoke method to call events in my event listener class at runtime.

Here is the the event I am calling using the call method:

@EventHandler
public static void onMinecraftInitialization(EventMinecraftInitialization event)
{
    // Do stuff
}

Here is the call method:

public void call(Event event)
{
    final EventData data = get(event.getClass());

    try
    {
        data.target.invoke(data.source, event); // Error here
    }
    catch (InvocationTargetException | IllegalAccessException e)
    {
        e.printStackTrace();
    }
}

I am also using mixins to register my event listener class, which works fine.

In a development enviroment this works fine and my minecraft mod runs. However, when I build my mod and attempt to use it in the Minecraft launcher it crashed, with the crash report of:

java.lang.VerifyError: Bad type on operand stack
Exception Details:
  Location:
    dev/mistercow1/sobyity/EventBus.call(Ldev/mistercow1/sobyity/Event;)V @33: invokevirtual
  Reason:
    Type 'java/lang/Object' (current frame, stack[0]) is not assignable to 
    'java/lang/ReflectiveOperationException'

dev/mistercow1/sobyity/EventBus.call(Ldev/mistercow1/sobyity/Event;)V @33 is the invoke in my call method.

Correction: dev/mistercow1/sobyity/EventBus.call(Ldev/mistercow1/sobyity/Event;)V @33 is the e.printStackTrace();

In my proguard mappings I have excluded the event library and the mixin package (so they do not get obfuscated), as that is required for minecraft to run, as it is packaged into the jar using shadowjar. I have also disabled shrinking and optimizing, and repackaged classes into the base directory (dev.mistercow1.minecraftmod)

Everything works fine in the deobfuscated version of my mod and in the development enviroment, so I am confused why the obfuscated version does not work.

I have already tried using data.target.invoke(null, event); instead, but it has no effect.

Is this a problem with my event system or minecraft mod or is this a problem with proguard?

Does anyone have any solution to this?

Edit: using -keep for the event package is ineffective, as I am not using something like Method m = ReflectMethodinvokeExample1.class.getDeclaredMethod("process", String.class); to find the method to invoke.


Solution

  • I fixed this by adding all the jmods in C:\Program Files\Java\jdk-16.0.2\jmods to -libraryjars, like:

    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.base.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.compiler.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.datatransfer.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.desktop.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.instrument.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.logging.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.management.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.management.rmi.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.naming.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.net.http.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.prefs.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.rmi.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.scripting.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.se.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.security.jgss.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.security.sasl.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.smartcardio.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.sql.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.sql.rowset.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.transaction.xa.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.xml.crypto.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\java.xml.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.accessibility.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.attach.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.charsets.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.compiler.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.crypto.cryptoki.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.crypto.ec.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.crypto.mscapi.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.dynalink.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.editpad.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.hotspot.agent.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.httpserver.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.incubator.foreign.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.incubator.vector.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.internal.ed.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.internal.jvmstat.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.internal.le.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.internal.opt.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.internal.vm.ci.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.jartool.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.javadoc.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.jcmd.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.jconsole.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.jdeps.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.jdi.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.jdwp.agent.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.jfr.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.jlink.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.jpackage.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.jshell.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.jsobject.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.jstatd.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.localedata.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.management.agent.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.management.jfr.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.management.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.naming.dns.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.naming.rmi.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.net.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.nio.mapmode.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.sctp.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.security.auth.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.security.jgss.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.unsupported.desktop.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.unsupported.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.xml.dom.jmod'
    -libraryjars 'C:\Program Files\Java\jdk-16.0.2\jmods\jdk.zipfs.jmod'
    

    Edit: Just put this in you proguard task in your build.gradle:

    fileTree("${System.properties['java.home']}\\jmods\\") {
        forEach() {
            libraryjars "${it.path}"
        }
    }