Jump to content
View in the app

A better way to browse. Learn more.

Forge Forums

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

[1.7.10] [SOLVED] ClassDefNotFound after ClassTransformer is called?

Featured Replies

Posted

Hey everyone,

 

I'm having a bit of a problem patching classes with ASM. I'm attempting to patch two functions, one in BiomeGenBase and one in ChunkProviderGenerate. The patching works fine for BiomeGenBase, however, the class cannot be found by the JVM once I've patched it. Here is my class transformer:

 

 

public class ClassTransformer implements IClassTransformer{

@Override
public byte[] transform(String name, String transformedName, byte[] bytes) {
	FMLRelaunchLog.warning("%s", name);
	if(find(name, class_biomeGenBase) != -1){
		ClassNode cNode = new ClassNode();
		ClassReader reader = new ClassReader(bytes);
		reader.accept(cNode, 0);
		MethodNode mNode = null;
		//FMLRelaunchLog.warning("%s", Arrays.toString(cNode.methods.toArray()));
		for(MethodNode node:cNode.methods){
			FMLRelaunchLog.warning("%s:%s", node.name, node.desc);
			if(find(node.name, method_genBiomeTerrain) != -1 && find(node.desc, desc_genBiomeTerrain) != -1){
				mNode = node;
				break;
			}
		}
		if(mNode == null){
			LogHelper.error("Failed to replace water!");
			return bytes;
		}
		boolean fixed = false;
		for(AbstractInsnNode node:mNode.instructions.toArray()){
			if(node instanceof FieldInsnNode){
				FieldInsnNode vNode = (FieldInsnNode) node;
				LogHelper.info(vNode.name);
				if(find(vNode.name, field_blockWater) != -1){
					node = vNode.getNext();
					if(node instanceof VarInsnNode && ((VarInsnNode)node).var == 10){
						vNode.owner = "me/superckl/betteroceans/common/reference/ModBlocks";
						vNode.name = "saltWater";
						vNode.desc = "Lme/superckl/betteroceans/common/fluid/block/BlockFluidSaltWater;";
						LogHelper.info("Patched "+name+"."+mNode.name);
						fixed = true;
						break;
					}
				}
			}
		}
		LogHelper.info("Writing class with fixed: "+fixed);
		ClassWriter cWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
		cNode.accept(cWriter);
		return cWriter.toByteArray();
	}else if(find(name, class_chunkProviderGenerate) != -1){
		ClassNode cNode = new ClassNode();
		ClassReader reader = new ClassReader(bytes);
		reader.accept(cNode, 0);
		MethodNode mNode = null;
		//FMLRelaunchLog.warning("%s", Arrays.toString(cNode.methods.toArray()));
		for(MethodNode node:cNode.methods){
			FMLRelaunchLog.warning("%s:%s", node.name, node.desc);
			if(find(node.name, method_func_147424_a) != -1 && find(node.desc, desc_func_147424_a) != -1){
				mNode = node;
				break;
			}
		}
		if(mNode == null){
			LogHelper.error("Failed to replace water!");
			return bytes;
		}
		for(AbstractInsnNode node:mNode.instructions.toArray()){
			if(node instanceof FieldInsnNode){
				FieldInsnNode vNode = (FieldInsnNode) node;
				if(find(vNode.name, field_blockWater) != -1){
					vNode.owner = "me/superckl/betteroceans/common/reference/ModBlocks";
					vNode.name = "saltWater";
					vNode.desc = "Lme/superckl/betteroceans/common/fluid/block/BlockFluidSaltWater;";
					LogHelper.info("Patched "+name+"."+mNode.name);
				}
			}
		}
		ClassWriter cWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
		cNode.accept(cWriter);
		return cWriter.toByteArray();
	}
	return bytes;
}

public static <T> int find(final T toFind, final T[] in){
	for(int i = 0; i < in.length; i++)
		if(in[i] == toFind || in[i].equals(toFind))
			return i;
	return -1;
}


	public static final String[] field_ocean = {"ocean", "field_76771_b"};
	public static final String[] field_deepOcean = {"deepOcean", "field_150575_M"};
	public static final String[] field_blockWater = {"water", "field_150355_j", "j"};

	public static final String[] method_genBiomeTerrain = {"genBiomeTerrain", "func_150560_b", "b"};
	public static final String[] method_func_147424_a = {"func_147424_a", "a"};

	public static final String[] desc_genBiomeTerrain = {"(Lnet/minecraft/world/World;Ljava/util/Random;[Lnet/minecraft/block/Block;[bIID)V", "(Lahb;Ljava/util/Random;[Laji;[bIID)V"};
	public static final String[] desc_func_147424_a = {"(II[Lnet/minecraft/block/Block;)V", "(II[Laji;)V"};

	public static final String[] class_biomeGenBase = {"net.minecraft.world.biome.BiomeGenBase", "ahu"};
	public static final String[] class_chunkProviderGenerate = {"net.minecraft.world.gen.ChunkProviderGenerate", "aqz"};

}

 

 

And the error I get:

 

 

java.lang.NoClassDefFoundError: me/superckl/betteroceans/common/gen/BiomeGenBetterOcean

at me.superckl.betteroceans.common.utility.BiomeHelper.replaceOceanBiomes(BiomeHelper.java:22) ~[biomeHelper.class:?]

at me.superckl.betteroceans.BetterOceans.init(BetterOceans.java:59) ~[betterOceans.class:?]

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_05]

at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_05]

at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_05]

at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_05]

at cpw.mods.fml.common.FMLModContainer.handleModStateEvent(FMLModContainer.java:513) ~[forge-1.7.10-10.13.0.1183.jar:?]

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_05]

at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_05]

at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_05]

at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_05]

at com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74) ~[guava-16.0.jar:?]

at com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47) ~[guava-16.0.jar:?]

at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322) ~[guava-16.0.jar:?]

at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304) ~[guava-16.0.jar:?]

at com.google.common.eventbus.EventBus.post(EventBus.java:275) ~[guava-16.0.jar:?]

at cpw.mods.fml.common.LoadController.sendEventToModContainer(LoadController.java:208) ~[forge-1.7.10-10.13.0.1183.jar:?]

at cpw.mods.fml.common.LoadController.propogateStateMessage(LoadController.java:187) ~[forge-1.7.10-10.13.0.1183.jar:?]

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_05]

at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_05]

at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_05]

at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_05]

at com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74) ~[guava-16.0.jar:?]

at com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47) ~[guava-16.0.jar:?]

at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322) ~[guava-16.0.jar:?]

at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304) ~[guava-16.0.jar:?]

at com.google.common.eventbus.EventBus.post(EventBus.java:275) ~[guava-16.0.jar:?]

at cpw.mods.fml.common.LoadController.distributeStateMessage(LoadController.java:118) [LoadController.class:?]

at cpw.mods.fml.common.Loader.initializeMods(Loader.java:691) [Loader.class:?]

at cpw.mods.fml.client.FMLClientHandler.finishMinecraftLoading(FMLClientHandler.java:288) [FMLClientHandler.class:?]

at net.minecraft.client.Minecraft.func_71384_a(Minecraft.java:541) [bao.class:?]

at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:867) [bao.class:?]

at net.minecraft.client.main.Main.main(SourceFile:148) [Main.class:?]

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_05]

at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_05]

at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_05]

at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_05]

at net.minecraft.launchwrapper.Launch.launch(Launch.java:134) [launchwrapper-1.9.jar:?]

at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.9.jar:?]

Caused by: java.lang.ClassNotFoundException: me.superckl.betteroceans.common.gen.BiomeGenBetterOcean

at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:188) ~[launchwrapper-1.9.jar:?]

at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_05]

at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_05]

... 39 more

Caused by: java.lang.NoClassDefFoundError: net/minecraft/world/biome/BiomeGenBase

at java.lang.ClassLoader.defineClass1(Native Method) ~[?:1.8.0_05]

at java.lang.ClassLoader.defineClass(Unknown Source) ~[?:1.8.0_05]

at java.security.SecureClassLoader.defineClass(Unknown Source) ~[?:1.8.0_05]

at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:180) ~[launchwrapper-1.9.jar:?]

at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_05]

at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_05]

... 39 more

Caused by: java.lang.ClassNotFoundException: net.minecraft.world.biome.BiomeGenBase

at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:99) ~[launchwrapper-1.9.jar:?]

at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_05]

at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_05]

at java.lang.ClassLoader.defineClass1(Native Method) ~[?:1.8.0_05]

at java.lang.ClassLoader.defineClass(Unknown Source) ~[?:1.8.0_05]

at java.security.SecureClassLoader.defineClass(Unknown Source) ~[?:1.8.0_05]

at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:180) ~[launchwrapper-1.9.jar:?]

at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_05]

at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_05]

... 39 more

 

 

The error is thrown on this line of code:

 

final BiomeGenBetterOcean boO = new BiomeGenBetterOcean(BiomeGenBase.ocean.biomeID);

If I remove the class transformer, everything works fine. I'm not entirely sure what is going on here... Maybe I'm doing something completely wrong her - It's my first time working with ASM.

 

Thanks for any help you can offer.

 

EDIT: I forgot to mention that it works fine in my eclipse development environment. The patch works and does what it's supposed to. It seems like the obfuscation is messing it up in some way.

 

EDIT 2: Fixed! I just applied a sorting index of > 1000 to get above the FML deobfuscater and it all worked!

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

Important Information

By using this site, you agree to our Terms of Use.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.