Reproducing "too many constants" Problem in Java

In my previous web log mail, I blogged on the "lawmaking besides large" problem and reproduced that error bulletin. In this mail service, I look at the very similar "besides many constants" error message (non the same thing as the question too many constants?) and demonstrate reproducing information technology by having likewise many methods in a generated Java class.

With a few small-scale adaptations, I can adjust the Groovy script that I used to generate a Java class to reproduce the "code likewise large" mistake to instead generate a Java class to reproduce the "too many constants" error. Here is the revised script.

generateJavaClassWithManyMethods.groovy

                #!/usr/bin/env groovy  import javax.tools.ToolProvider  println "You lot're running the script ${Organisation.getProperty('script.name')}" if (args.length < 2) {    println "Usage: javaClassGenerationWithManyMethods packageName className baseDir #methods"    System.exit(-1) }  // No use of "def" makes the variable available to entire script including the // divers methods ("global" variables)  packageName = args[0] packagePieces = packageName.tokenize(".")  // Become directory names def fileName = args[1].endsWith(".java") ? args[i] : args[1] + ".java" def baseDirectory = args.length > 2 ? args[2] : Organisation.getProperty("user.dir") numberOfMethods = args.length > 3 ? Integer.valueOf(args[three]) : 10  NEW_LINE = System.getProperty("line.separator")  // The setting upwards of the indentations shows off Slap-up's easy characteristic for // multiplying Strings and Groovy's tie of an overloaded * operator for Strings // to the 'multiply' method.  In other words, the "multiply" and "*" used hither // are really the same affair. SINGLE_INDENT = '   ' DOUBLE_INDENT = SINGLE_INDENT.multiply(2) TRIPLE_INDENT = SINGLE_INDENT * 3  def outputDirectoryName = createDirectories(baseDirectory) def generatedJavaFile = generateJavaClass(outputDirectoryName, fileName) compileJavaClass(generatedJavaFile)   /**  * Generate the Java class and write its source lawmaking to the output directory  * provided and with the file name provided.  The generated class's proper noun is  * derived from the provided file proper name.  *  * @param outDirName Name of directory to which to write Coffee source.  * @param fileName Name of file to exist written to output directory (should include  *    the .coffee extension).  * @return Fully qualified file name of source file.  */ def String generateJavaClass(outDirName, fileName) {    def className = fileName.substring(0,fileName.size()-five)    outputFileName = outDirName.toString() + File.separator + fileName    outputFile = new File(outputFileName)    outputFile.write "packet ${packageName};${NEW_LINE.multiply(2)}"      outputFile << "public class ${className}${NEW_LINE}"      outputFile << "{${NEW_LINE}"    outputFile << "${SINGLE_INDENT}public static void main(final Cord[] arguments)"    outputFile << "${NEW_LINE}${SINGLE_INDENT}{${NEW_LINE}"    outputFile << DOUBLE_INDENT << 'terminal String someString = "Dustin";' << NEW_LINE    outputFile << "${SINGLE_INDENT}}${NEW_LINE}"    outputFile << buildManyMethods()    outputFile << "}"    return outputFileName }   /**  * Compile the provided Java source code file proper noun.  *  * @param fileName Name of Java file to be compiled.  */ def void compileJavaClass(fileName) {    // Apply the Coffee SE 6 Compiler API (JSR 199)    // http://java.lord's day.com/mailers/techtips/corejava/2007/tt0307.html#1    compiler = ToolProvider.getSystemJavaCompiler()        // The employ of nulls in the phone call to JavaCompiler.run indicate use of defaults    // of Organisation.in, Organisation.out, and System.err.     int compilationResult = compiler.run(nothing, zip, goose egg, fileName)    if (compilationResult == 0)    {       println "${fileName} compiled successfully"  }    else    {       println "${fileName} compilation failed"    } }   /**  * Create directories to which generated files will be written.  *  * @param baseDir The base directory used in which subdirectories for Java  *    source packages will be generated.  */ def String createDirectories(baseDir) {    def outDirName = new StringBuilder(baseDir)    for (pkgDir in packagePieces)    {       outDirName << File.separator << pkgDir    }    outputDirectory = new File(outDirName.toString())    if (outputDirectory.exists() && outputDirectory.isDirectory())    {       println "Directory ${outDirName} already exists."    }    else    {       isDirectoryCreated = outputDirectory.mkdirs()  // Use mkdirs in case multiple       println "Directory ${outputDirectoryName} ${isDirectoryCreated ? 'is' : 'non'} created."    }    render outDirName.toString() }   /**  * Generate the trunk of generated Java grade source code'south master function.  */ def String buildManyMethods() {    def str = new StringBuilder() << NEW_LINE    for (i in 0..numberOfMethods)    {       str << SINGLE_INDENT << "private void doMethod${i}(){}" << NEW_LINE    }    render str }                              

When the above script is run with a parameter of 5 for the number of methods, the following Coffee code is generated.

                packet dustin.examples;  public grade LotsOfMethods {    public static void primary(final String[] arguments)    {       final String someString = "Dustin";    }     private void doMethod0(){}    private void doMethod1(){}    private void doMethod2(){}    private void doMethod3(){}    private void doMethod4(){}    private void doMethod5(){} }                              

When I turn upwardly the number of generated methods to 65000 methods, I run out of heap space as shown in the next screen snapshot.

The side by side screen snapshot shows the output of running the script again, merely this time with 512 MB maximum heap infinite specified for the JVM.

What happens when we endeavor to compile a class with as well many methods? That is shown in the next screen snapshot that demonstrates what happens when just such a compilation is attempted.

The "besides many constants" error message is shown with a pointer at the course keyword in the grade definition. The method has too many methods to compile.

When I run javap -c -private dustin.examples.LotsOfMethods (-c to disassemble the lawmaking, -private to display the many private methods, and dustin.examples.LotsOfMethods is the proper name of the generated Java form), I see output like the post-obit (simply the beginning and end shown instead of displaying all 60,000+ methods).

                Compiled from "LotsOfMethods.java" public class dustin.examples.LotsOfMethods extends java.lang.Object{ public dustin.examples.LotsOfMethods();   Code:    0: aload_0    one: invokespecial #1; //Method java/lang/Object."<init>":()5    4: render  public static void main(coffee.lang.Cord[]);   Code:    0: return  private void doMethod0();   Lawmaking:    0: render  private void doMethod1();   Lawmaking:    0: render  private void doMethod2();   Code:    0: render  private void doMethod3();   Code:    0: return  individual void doMethod4();   Lawmaking:    0: return  private void doMethod5();   Code:    0: render  private void doMethod6();   Code:    0: return  private void doMethod7();   Code:    0: return  private void doMethod8();   Code:    0: return  . . .  . . .  . . .  private void doMethod64992();   Lawmaking:    0: return  private void doMethod64993();   Code:    0: return  private void doMethod64994();   Lawmaking:    0: return  individual void doMethod64995();   Code:    0: render  private void doMethod64996();   Code:    0: return  individual void doMethod64997();   Code:    0: return  private void doMethod64998();   Code:    0: return  private void doMethod64999();   Code:    0: return  private void doMethod65000();   Code:    0: return  }                              

Decision

Equally with the last blog mail service, this post used Bully and the Java Compiler API to intentionally reproduce an mistake that we hope to not encounter very often.

Additional Reference

Error Writing File: as well many constants

This story, "Reproducing "too many constants" Trouble in Java" was originally published by JavaWorld .

Copyright © 2010 IDG Communications, Inc.