I’m getting the following exception thrown when make an android build from Unity ( this shows up in my Unity console )
Error building Player: CommandInvokationFailure: Unable to convert classes into dex format. See the Console for details.
C:\Program Files\Java\jdk1.8.0_20\bin\java.exe -Xmx1024M -Dcom.android.sdkmanager.toolsdir=“C:/adt-bundle-windows-x86-20140702/sdk ools” -Dfile.encoding=UTF8 -jar “C:/Program Files (x86)/Unity/Data/BuildTargetTools/AndroidPlayer\sdktools.jar” -
stderr[
UNEXPECTED TOP-LEVEL ERROR:
java.lang.OutOfMemoryError: GC overhead limit exceeded
at com.android.dx.rop.code.RopMethod.calcPredecessors(RopMethod.java:173)
at com.android.dx.rop.code.RopMethod.labelToPredecessors(RopMethod.java:94)
at com.android.dx.ssa.SsaBasicBlock.newFromRop(SsaBasicBlock.java:157)
at com.android.dx.ssa.SsaMethod.convertRopToSsaBlocks(SsaMethod.java:173)
at com.android.dx.ssa.SsaMethod.newFromRopMethod(SsaMethod.java:103)
at com.android.dx.ssa.SsaConverter.convertToSsaMethod(SsaConverter.java:44)
at com.android.dx.ssa.Optimizer.optimize(Optimizer.java:98)
at com.android.dx.ssa.Optimizer.optimize(Optimizer.java:72)
at com.android.dx.dex.cf.CfTranslator.processMethods(CfTranslator.java:299)
at com.android.dx.dex.cf.CfTranslator.translate0(CfTranslator.java:139)
at com.android.dx.dex.cf.CfTranslator.translate(CfTranslator.java:94)
at com.android.dx.command.dexer.Main.processClass(Main.java:682)
at com.android.dx.command.dexer.Main.processFileBytes(Main.java:634)
at com.android.dx.command.dexer.Main.access$600(Main.java:78)
at com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:572)
at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:284)
at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:166)
at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:144)
at com.android.dx.command.dexer.Main.processOne(Main.java:596)
at com.android.dx.command.dexer.Main.processAllFiles(Main.java:498)
at com.android.dx.command.dexer.Main.runMonoDex(Main.java:264)
at com.android.dx.command.dexer.Main.run(Main.java:230)
at com.android.dx.command.dexer.Main.main(Main.java:199)
at com.android.dx.command.Main.main(Main.java:103)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at SDKMain.main(SDKMain.java:129)
As far as I can tell, I need the -Xmx1024M to be something biffer like -Xmx2048. However, I have no idea how to tell Unity to use a bigger number there. I’m using version 4.5.5p2. This just started happening when I added yet another piece of middleware which, unfortunately, I need to include.
If anybody runs into this, I solved this with an evil hack. first, rename your java.exe to java-default.exe. Then replace compile a new java.exe from this c# program. Note it will then use 2048mb to compile ( or change that value down below to use however much you want! )
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.IO;
namespace CommandlineInterceptor
{
class Program
{
static void Main( string[] args )
{
//let's get the exe from our assembly location
string exeLocation = typeof( Program ).Assembly.Location;
//now to get the real location, right before the .exe, add -default
exeLocation = exeLocation.Replace( ".exe", "-default.exe" );
//string javaExe = @"C:\Program Files\Java\jdk1.8.0_20\bin\java-default.exe";
string javaExe = exeLocation;
//go through the arguments and replace anything that starts with -Xmx
string arguments = GetFilteredArgString( args );
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = javaExe;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardInput = true;
startInfo.Arguments = arguments;
//startInfo.RedirectStandardInput = true;
using( Process process = new Process() )
{
process.StartInfo = startInfo;
process.OutputDataReceived += new DataReceivedEventHandler( HandleOutputData );
process.ErrorDataReceived += new DataReceivedEventHandler( HandleErrorData );
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
Stream inputStream = Console.OpenStandardInput();
string allInput = Console.In.ReadToEnd();
process.StandardInput.Write( allInput );
process.WaitForExit();
}
}
private static void HandleOutputData( object inProcess, DataReceivedEventArgs inLine )
{
//send the data to the console, no matter what it is...
Console.Out.WriteLine( inLine.Data );
}
private static void HandleErrorData( object inProcess, DataReceivedEventArgs inLine )
{
//send the data to the console, no matter what it is...
Console.Error.WriteLine( inLine.Data );
}
private static string GetFilteredArgString( string[] inArgs )
{
StringBuilder sb = new StringBuilder();
foreach ( string arg in inArgs )
{
if( arg.Contains( "-Xmx" ) )
{
sb.Append( "-Xmx2048 " );
}
else
{
sb.Append( arg );
sb.Append( " ") ;
}
}
return sb.ToString();
}
}
}
By the way, if you’re using OSX, the following bash script will also do the job:
#!/bin/bash
# Script to override the memory size for java so that it doesn't barf on large Unity projects
/usr/bin/java.original ${@/Xmx1024M/Xmx2048M}
Save the above file to a file called ‘java’, then do the following: