Generic Java Runtime
Run arbitrary Java apps on Witchly.host. Upload your JAR and run it with configurable flags — great for bots, Spring Boot apps, and custom server software.
languages (12 articles)
On This Page
Generic Java Runtime
The Generic Java egg runs any executable JAR with Java 8. It’s a minimal, flexible runtime — upload your .jar, set the filename, start the server. Great for Discord bots (JDA, Discord4J), Spring Boot microservices, and custom tooling.
Note: This egg is configured for Java 8. For newer Java versions (17, 21, etc.), most Minecraft-focused eggs have better defaults — or contact support to have a custom egg provisioned.
Quick deploy
- dash.witchly.host → Deploy → Languages → Generic Java.
- SFTP your
.jarfile to/home/container/. - On the Startup tab, set
JAR FILEto your JAR’s filename. - Start.
Startup flow
java -Dterminal.jline=false -Dterminal.ansi=true -jar {{JARFILE}}
Everything after the -jar is fixed to your JAR file. Customize JVM flags by editing the startup command:
java -Xmx${SERVER_MEMORY}M -Xms512M \
-Dterminal.jline=false -Dterminal.ansi=true \
-jar {{JARFILE}}
Variables reference
| Variable | Purpose |
|---|---|
JARFILE | Name of your JAR in /home/container/ |
That’s it — this is a minimal egg. Any other configuration happens in your JAR, via application.properties, env vars, or CLI args.
Memory tuning
Java doesn’t know about cgroup memory limits prior to Java 10. Always set -Xmx explicitly:
-Xmx${SERVER_MEMORY}M → caps the JVM heap at your plan's RAM
On The Script (512 MB), try -Xmx400M — leaving ~100 MB for metaspace and native memory. On larger plans you can use more of the RAM.
Spring Boot example
Build your Spring Boot fat JAR locally:
./mvnw clean package
# produces target/myapp-0.0.1-SNAPSHOT.jar
SFTP the JAR to /home/container/, set JARFILE = myapp-0.0.1-SNAPSHOT.jar, and update the startup to bind the port:
java -Xmx${SERVER_MEMORY}M \
-Dserver.port=${SERVER_PORT} \
-jar {{JARFILE}}
Your app is reachable at your server’s IP:PORT.
JDA Discord bot example
// Bot.java
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.requests.GatewayIntent;
public class Bot {
public static void main(String[] args) throws Exception {
JDABuilder.createDefault(System.getenv("DISCORD_TOKEN"))
.enableIntents(GatewayIntent.MESSAGE_CONTENT)
.build();
}
}
Build a fat JAR with the shade/assembly plugin, upload, set DISCORD_TOKEN via env, start.
Setting environment variables
Pterodactyl variables appear as process.env-equivalent in Java. Either read them directly with System.getenv("DISCORD_TOKEN") or pass them in the startup:
java -DdiscordToken=${DISCORD_TOKEN} -jar {{JARFILE}}
then in Java: System.getProperty("discordToken").
Troubleshooting
- “Could not find or load main class” — your JAR isn’t executable. Check
MANIFEST.MFhasMain-Class:, or use a shaded/fat JAR builder. - OutOfMemoryError — raise
-Xmxor upgrade your plan. - ClassNotFoundException — your dependencies aren’t bundled; build a shaded/fat JAR or upload dependencies to
/home/container/libs/and add them to the classpath.