How do I get Unity to increase the amount of memory passed on the command line to the jvm when making a build for Android?

Hi everybody!

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.

Thanks!

Josh

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:

chmod 755 java
sudo mv /usr/bin/java /usr/bin/java.original
sudo mv java /usr/bin/java

Hey guys, this has been fixed in Unity 4.6.1p3:

http://unity3d.com/unity/qa/patch-releases

(none) - Android: Increase maximum memory available to Java when building for Android.

Cheers!

If building system is Gradle…

Build, but check “Export Project”

Add this to build.gradle on the exported project

android {
    ...
        dexOptions {
            javaMaxHeapSize "2g"
        }
    ...
    }

Copy build,gradle to Assets/Plugins/Android/mainTemplate.gradle

Build APK

Remember to repeat this if you install any other android plugin

I deleted all .webm video files from my project.
I also made sure to transcode any other videos.

Now it builds fine.