Skip to content

Commit

Permalink
Added JMX debug connector as first part of automated mod testing
Browse files Browse the repository at this point in the history
  • Loading branch information
jediminer543 committed Dec 21, 2021
1 parent 13a54eb commit f5359cb
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/main/java/org/jmt/mcmt/MCMT.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.jmt.mcmt.commands.ConfigCommand;
import org.jmt.mcmt.commands.StatsCommand;
import org.jmt.mcmt.config.GeneralConfig;
import org.jmt.mcmt.jmx.JMXRegistration;
import org.jmt.mcmt.serdes.SerDesRegistry;

import com.mojang.brigadier.CommandDispatcher;
Expand Down Expand Up @@ -46,6 +47,10 @@ public MCMT() {
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::processIMC);
// Register the doClientStuff method for modloading
//FMLJavaModLoadingContext.get().getModEventBus().addListener(this::doClientStuff);

if (System.getProperty("jmt.mcmt.jmx") != null) {
JMXRegistration.register();
}

// Register ourselves for server and other game events we are interested in
MinecraftForge.EVENT_BUS.register(this);
Expand Down
25 changes: 24 additions & 1 deletion src/main/java/org/jmt/mcmt/asmdest/DebugHookTerminator.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.LockSupport;
import java.util.function.BooleanSupplier;

Expand All @@ -14,6 +16,7 @@

import com.mojang.datafixers.util.Either;

import net.minecraft.client.Minecraft;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.registry.MutableRegistry;
Expand Down Expand Up @@ -58,29 +61,49 @@ public BrokenChunkLocator(long chunkPos, CompletableFuture<?> maincf, Completabl
this.maincf = maincf;
this.brokecf = brokecf;
}
public long getChunkPos() {
return chunkPos;
}

}

public static List<BrokenChunkLocator> breaks = new ArrayList<>();

public static boolean isBypassLoadTarget() {
return bypassLoadTarget;
}

public static AtomicBoolean mainThreadChunkLoad = new AtomicBoolean();
public static AtomicLong mainThreadChunkLoadCount = new AtomicLong();
public static String mainThread = "Server thread";

public static void chunkLoadDrive(ServerChunkProvider.ChunkExecutor executor, BooleanSupplier isDone, ServerChunkProvider scp,
CompletableFuture<Either<IChunk, IChunkLoadingError>> completableFuture, long chunkpos) {
/*
if (!GeneralConfig.enableChunkTimeout) {
bypassLoadTarget = false;
executor.driveUntil(isDone);
return;
}
*/
int failcount = 0;
if (Thread.currentThread().getName().equals(mainThread)) {
mainThreadChunkLoadCount.set(0);
mainThreadChunkLoad.set(true);
}
while (!isDone.getAsBoolean()) {
if (!executor.driveOne()) {
if(isDone.getAsBoolean()) {
if (Thread.currentThread().getName().equals(mainThread)) {
mainThreadChunkLoad.set(false);
}
break;
}
// Nothing more to execute
if (failcount++ < GeneralConfig.timeoutCount) {
if (!GeneralConfig.enableChunkTimeout || failcount++ < GeneralConfig.timeoutCount) {
if (Thread.currentThread().getName().equals(mainThread)) {
mainThreadChunkLoadCount.incrementAndGet();
}
Thread.yield();
LockSupport.parkNanos("THE END IS ~~NEVER~~ LOADING", 100000L);
} else {
Expand Down
34 changes: 34 additions & 0 deletions src/main/java/org/jmt/mcmt/jmx/JMXRegistration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.jmt.mcmt.jmx;

import java.lang.management.ManagementFactory;

import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;

public class JMXRegistration {

public static void register() {
try {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName debugName = new ObjectName("org.jmt.mcmt:type=MCMTDebug");
MCMTDebug debugBean = new MCMTDebug();
mbs.registerMBean(debugBean, debugName);
} catch (MalformedObjectNameException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstanceAlreadyExistsException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (MBeanRegistrationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NotCompliantMBeanException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
58 changes: 58 additions & 0 deletions src/main/java/org/jmt/mcmt/jmx/MCMTDebug.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package org.jmt.mcmt.jmx;

import javax.management.AttributeChangeNotification;
import javax.management.MBeanNotificationInfo;
import javax.management.NotificationBroadcasterSupport;

import org.jmt.mcmt.asmdest.DebugHookTerminator;

import net.minecraft.util.math.ChunkPos;
import net.minecraftforge.fml.ModList;

/**
* MBean for debugging modlaunching issues
*
* @author jediminer543
*
*/
public class MCMTDebug extends NotificationBroadcasterSupport implements MCMTDebugMBean {

ClassLoader ccl = null;

public MCMTDebug() {
// needed because classloading issues; classload all TRANSFORMER classes before stuff
ccl = Thread.currentThread().getContextClassLoader();
}

@Override
public String[] getLoadedMods() {
Thread.currentThread().setContextClassLoader(ccl);
return ModList.get().applyForEachModContainer(mc -> mc.getModId()+":"+mc.getModInfo().getVersion().toString()).toArray(String[]::new);
}

@Override
public String getMainChunkLoadStatus() {
Thread.currentThread().setContextClassLoader(ccl);
return DebugHookTerminator.mainThreadChunkLoad.get() + ":" + DebugHookTerminator.mainThreadChunkLoadCount.get();
}

@Override
public String[] getBrokenChunkList() {
Thread.currentThread().setContextClassLoader(ccl);
return DebugHookTerminator.breaks.stream().map(bcl -> new ChunkPos(bcl.getChunkPos()).toString()).toArray(String[]::new);
}

@Override
public MBeanNotificationInfo[] getNotificationInfo() {
String[] types = new String[]{
AttributeChangeNotification.ATTRIBUTE_CHANGE
};

String name = AttributeChangeNotification.class.getName();
String description = "An attribute of this MBean has changed";
MBeanNotificationInfo info =
new MBeanNotificationInfo(types, name, description);
return new MBeanNotificationInfo[]{info};
}

}
11 changes: 11 additions & 0 deletions src/main/java/org/jmt/mcmt/jmx/MCMTDebugMBean.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.jmt.mcmt.jmx;

public interface MCMTDebugMBean {

public String[] getLoadedMods();

public String getMainChunkLoadStatus();

public String[] getBrokenChunkList();

}

0 comments on commit f5359cb

Please sign in to comment.