Revision: 7430
Author: [email protected]
Date: Tue Jan 19 11:56:46 2010
Log: Provides an alternative way to encode text strings for TextResorurces when they exceed a certain size. Extremely large resources (12MB in my tests) caused the
GWT compiler to crash with an Out of Memory exception.

Review by: robertvawter

http://code.google.com/p/google-web-toolkit/source/detail?r=7430

Added:
 /trunk/user/test/com/google/gwt/resources/client/bigtextresource.txt
Modified:
 /trunk/user/src/com/google/gwt/resources/rg/TextResourceGenerator.java
 /trunk/user/test/com/google/gwt/resources/ResourcesSuite.java
 /trunk/user/test/com/google/gwt/resources/client/TextResourceTest.java

=======================================
--- /dev/null   
+++ /trunk/user/test/com/google/gwt/resources/client/bigtextresource.txt Tue Jan 19 11:56:46 2010
File is too large to display a diff.
=======================================
--- /trunk/user/src/com/google/gwt/resources/rg/TextResourceGenerator.java Tue Aug 25 15:27:02 2009 +++ /trunk/user/src/com/google/gwt/resources/rg/TextResourceGenerator.java Tue Jan 19 11:56:46 2010
@@ -33,6 +33,12 @@
  * Provides implementations of TextResource.
  */
public final class TextResourceGenerator extends AbstractResourceGenerator {
+  /**
+ * Java compiler has a limit of 2^16 bytes for encoding string constants in a + * class file. Since the max size of a character is 4 bytes, we'll limit the
+   * number of characters to (2^14 - 1) to fit within one record.
+   */
+  private static final int MAX_STRING_CHUNK = 16383;

   @Override
public String createAssignment(TreeLogger logger, ResourceContext context,
@@ -61,7 +67,11 @@

     String toWrite = Util.readURLAsString(resource);

-    sw.println("return \"" + Generator.escape(toWrite) + "\";");
+    if (toWrite.length() > MAX_STRING_CHUNK) {
+      writeLongString(sw, toWrite);
+    } else {
+      sw.println("return \"" + Generator.escape(toWrite) + "\";");
+    }
     sw.outdent();
     sw.println("}");

@@ -76,4 +86,23 @@

     return sw.toString();
   }
-}
+
+  /**
+ * A single constant that is too long will crash the compiler with an out of + * memory error. Break up the constant and generate code that appends using a
+   * buffer.
+   */
+  private void writeLongString(SourceWriter sw, String toWrite) {
+    sw.println("StringBuilder builder = new StringBuilder();");
+    int offset = 0;
+    int length = toWrite.length();
+    while (offset < length - 1) {
+      int subLength = Math.min(MAX_STRING_CHUNK, length - offset);
+      sw.print("builder.append(\"");
+ sw.print(Generator.escape(toWrite.substring(offset, offset + subLength)));
+      sw.println("\");");
+      offset += subLength;
+    }
+    sw.println("return builder.toString();");
+  }
+}
=======================================
--- /trunk/user/test/com/google/gwt/resources/ResourcesSuite.java Tue Dec 15 16:53:51 2009 +++ /trunk/user/test/com/google/gwt/resources/ResourcesSuite.java Tue Jan 19 11:56:46 2010
@@ -46,7 +46,6 @@
     suite.addTestSuite(NestedBundleTest.class);
     suite.addTestSuite(ResourceGeneratorUtilTest.class);
     suite.addTestSuite(TextResourceTest.class);
-
     return suite;
   }
 }
=======================================
--- /trunk/user/test/com/google/gwt/resources/client/TextResourceTest.java Wed Sep 30 16:46:38 2009 +++ /trunk/user/test/com/google/gwt/resources/client/TextResourceTest.java Tue Jan 19 11:56:46 2010
@@ -24,6 +24,9 @@
 public class TextResourceTest extends GWTTestCase {

   static interface Resources extends ClientBundleWithLookup {
+    @Source("bigtextresource.txt")
+    TextResource bigTextResource();
+
     @Source("com/google/gwt/resources/client/hello.txt")
     TextResource helloWorldAbsolute();

@@ -43,6 +46,17 @@
   public String getModuleName() {
     return "com.google.gwt.resources.Resources";
   }
+
+  /**
+ * Test fix for problem where large text files caused out of memory errors
+   * when run in hosted mode.
+   */
+  public void testBigTextResource() {
+    final Resources r = GWT.create(Resources.class);
+    String result = r.bigTextResource().getText();
+    int length = result.length();
+    assertEquals(length, 12737792);
+  }

   public void testExternal() throws ResourceException {
     final Resources r = GWT.create(Resources.class);
@@ -79,7 +93,7 @@
     assertEquals("helloWorldExternal", r.helloWorldExternal().getName());

     ResourcePrototype[] resources = r.getResources();
-    assertEquals(4, resources.length);
+    assertEquals(5, resources.length);
   }

   public void testOutsideResourceOracle() {
-- 
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to