4 Replies Latest reply on Sep 8, 2008 8:59 AM by Patrick Leckey

    Memory usage Acrobat Pro using Javascript

      Apologies in advance for long post.
      I am developing a reporting application using Adobe Acrobat
      Professional v8.1 (version 8.1.2). The project consists of
      some database operations with the results used to create PDF
      report file output. I am new to both Javascript and Acrobat
      Pro.

      The PDF output is created programmatically using Adobe Folder Level
      Javascript. No user interaction with the product is desired or
      required. The PDF files being produced vary in size depending on the
      amount of source data, and consist mainly of data extracted/reduced
      /calculated being placed into the PDF file in text fields.

      The Javascript works fine, and produces the desired output. The
      problem is that once a PDF file being produced is closed, Acrobat.exe
      continues to utilize system memory and will not release it. This
      causes Acrobat.exe to either freeze or fail once system memory is
      exhausted. The Acrobat.exe application must itself be closed to
      release the system memory - closing the document does not
      accomplish this. It has the appearance of a memory leak.

      The basic problem is that creation of (field or link) object content
      seems to cause system memory consumption not associated with the PDF
      document which persists as though no garbage collection process takes
      place after the document is closed. I am hoping I am wrong and that
      there is something I am doing wrong which can be corrected to avoid
      the problem.

      I have tried this on several systems with exactly the same results.

      Software Information:
      Adobe Acrobat Professional v8 (version 8.1.2)
      Acrobat was installed with all options with no problems.
      Preferences edited to enable Javascript & Javascript console.
      Preferences edited (and registry per Adobe TechNote) to enable ADBC
      used for ODBC database access
      Updates current thru 4/11/2008

      OS:
      Windows XP Porfessional SP2 32bit
      Updates current thru 4/11/2008
      (Has also been tried on other systems running Win XP and on systems
      running Windows Server 2003 R2 with same results).

      I have included some folder level Javascript and a test procedure which
      should allow the problem to be reproduced. The script simply uses the
      doc.addField method to add text fields to a new document.

      Although this example uses text fields, I have had exactly the same
      issue using button fields, and link objects.

      Test Procedure to Duplicate the Problem

      On a PC running Windows XP Pro SP2, with Adobe Acrobat Professional
      v8.1.2 installed with default options, with preferences set to enable
      Javascript (see above). No other user apps running:

      (0) Adobe Acrobat Professional is closed (not running). The folder
      C:\temp exists and logged in user has full access to this folder.
      (1) Copy the PageField.js file containing the folder level Javascript
      to:

      C:\Program Files\Adobe\Acrobat 8.0\Acrobat\Javascripts

      No other user Javascripts loaded.

      (2) Start Windows Task Manager and minimize it.
      (3) Start Adobe Acrobat Professional (do not open any document, simply
      start the Acrobat application).
      Open the Javascript console (Ctrl-J) and clear the console window.
      (4) Restore Task Manager, select the Processes tab and sort the tasks
      by Image Name. Locate Acrobat.exe and record the Mem Usage. (You
      may need to wait 30 secs or so for this value to become stable as
      initialization completes.)
      (5) Click on the Task Manager Performance tab, and record the values
      of PF Usage (Pagefile) and Available Physical Memory.
      Record these values once they are stable after Acrobat startup.
      (6) Minimize Task Manager. Return focus to the Javascript console,
      and type the following command in the console as shown:

      fnMakePDF("/c/temp/TestFile.pdf", 100);

      This calls the folder level function fnMakePDF in the folder-level
      Javascript file, and will cause it to create a PDF file
      ( C:\temp\TestFile.pdf ) containing 100 pages. E
        • 1. Re: Memory usage Acrobat Pro using Javascript
          Level 1
          Original post cut short, here is balance of info:

          This calls the folder level function fnMakePDF in the folder-level
          Javascript file, and will cause it to create a PDF file
          ( C:\temp\TestFile.pdf ) containing 100 pages. Each page has 256
          text fields on it (uniquely named), created using the doc.addField
          method. When the document creation is complete the function saves
          the document file to disk, and closes the document, leaving Acrobat
          running - once again with no file open.

          To execute the function, place the cursor on the line of the
          function call, and press Ctrl-ENTER. With the parameters set as
          above, the function may take a few minutes to complete as it
          creates the document.
          (7) When the function completes, the test file will have been created,
          written to disk, and closed by the Acrobat program. Now reexamine
          the memory usages that were recorded in steps 4 & 5 above.
          (8) Close the Acrobat.exe program, wait for memory to be released,
          and record same values as above.

          Using the procedure outlined above I typically see over 80mb of RAM not
          being released to the system and well over 100mb of pagefile allocation.
          This may not sound serious on PCs with gigabytes of installed RAM,
          however while executing the real world application, have observed RAM
          as large as 800 mb not being released as well as pagefile allocations,
          and this issue on large data sets causes Acrobat to hang or crash.
          Crashes seem to occur when pagefile resources are exhausted.

          I hope this is a problem with my script? If so how can I correct it?
          Is there some preference setting or configuration item(s) I need to
          change to get garbage collection to kick in and release the memory?
          Is this a known bug?

          Going through the developer documentation we have tried a great number
          of work-arounds to no avail (including flattening the document), and
          have received no help via Adobe tech support. All help & suggestions
          welcome.

          Javascript for test:

          // ****************************************************************
          // function fnAddRowField
          // Purpose: Places a text field object on a document. Placement
          // uses a coordinate system where the page is composed
          // of 64 rows, numbered from 1 to 64. Row 1 is at the
          // bottom of the page and row 64 at the top.
          //
          // Args: nDoc = the document object to be modified must be
          // opened already & passed to this function.
          // nPg = the page number of the document to operate
          // upon. (Page numbers start with 0).
          // nRow = the number of the page body row to place the
          // field on. Row 1 is a the bottom of the page
          // body, and row 64 is at the top.
          // LeftX = The Left X coordinate of the field in
          // points. This value is number of points
          // to the right of the left margin.
          // WideX = The width of the field in points.
          // fieldName = The base name of the created field.
          // Value = The value to be set into the field.
          //
          // Returns: Nothing. Creates an Acrobat Text Field object on
          // the specified page with the specified properties &
          // value.
          // ****************************************************************
          function fnAddRowField(nDoc, nPg, nRow, LeftX, WideX, fieldName, Value)
          {
          // *** This block of code calculates the quad coords for the field ***
          if ((nRow < 1) || (nRow > 64)) {
          return;
          };
          var Inch = 72; // Points per Inch conversion factor
          var locArray = new Array(); // Array for field's bounding rect coords
          var useHeight = 1;
          if ((nRow - useHeight) < 0) {
          useHeight = nRow;
          };
          var boxHeight = 12;
          var Margin = 0.30 * Inch;
          Margin = Math.round(Margin);

          var pageArray = new Array();
          pageArray = nDoc.getPageBox({cBox: "Crop", nPage: nPg});
          var MaximumWidth = pageArray[2] - LeftX - Margin;
          if (WideX < 0) {
          WideX = MaximumWidth;
          };
          locArray[0] = LeftX + Margin;
          locArray[1] = pageArray[1];
          locArray[2] = locArray[0] + WideX + 1;
          if (locArray[2] > (pageArray[2] - Margin)) {
          locArray[2] = pageArray[2] - Margin;
          };
          locArray[3] = locArray[1] - boxHeight;
          var Offset = (2.5 * boxHeight) + Margin - 1;
          Offset = Math.round(Offset) + 2;
          var boxCount = nRow;
          // Unique field name
          var fname = (fieldName + "P" + nPg + "R" + nRow + "L" + LeftX);
          // Calc coords of bounding box for field
          locArray[1] = (boxCount * boxHeight) + Offset - boxCount - 3;
          locArray[3] = locArray[1] - (boxHeight * useHeight) + useHeight;
          locArray[1] = locArray[1] + 1;
          // *** END block of code that calculates the quad coords for field ***

          // place the field on the form & format it
          //app.beginPriv();
          var f = nDoc.addField(fname, "text", nPg, locArray);
          f.textFont = font.Helv;
          f.fillColor = color.yellow;
          f.alignment = "center";
          f.textSize = 9;
          f.textColor = color.blue;
          f.linewidth = 1;
          f.borderStyle = border.s;
          f.strokeColor = color.green;
          f.multiline = false;
          f.display = display.visible;
          f.readonly = true;
          f.value = Value;

          f = undefined;
          //app.endPriv();
          return;
          };
          // ****************************************************************************
          // fnMakePDF - Create a PDF document with specified number of pages.
          // On each page, make a number of uniquely named text fields
          // of 64 rows x 4 columns (256 fields per page)
          //
          // Args: outFile = string value of the output PDF file to create
          // (example: "/c/temp/MyFile.pdf")
          // howManyPages = an integer value which is the number of pages
          // to create in the new PDF file
          //
          // Sample call: fnMakePDF("/c/temp/TestFile.pdf", 100)
          //
          // This would create a file called 'TestFile.pdf' in the
          // folder C:\temp . The file would have 100 pages, each with
          // 256 uniquely named text fields on it.
          //
          // Returns: Nothing. Creates the PDF document specified by outFile
          // ****************************************************************************
          fnMakePDF = app.trustedFunction( function (outFile,howManyPages)
          {
          app.beginPriv();

          var doc = app.newDoc({cPath: outFile}); // create new document file
          doc.saveAs({cPath: outFile}); // Save it (or overwrite old)
          var startX = 0; // init variable
          var fldText = " ";

          for (var numPg = 0; numPg < howManyPages; numPg++) { // Pages to create
          for (var numRow = 1; numRow < 65; numRow++) { // 64 'rows' per pg
          for (var numCol = 0; numCol < 4; numCol++) { // 4 cols per 'row'
          // calc column horiz starting location in points,
          // then place the field on the page
          startX = (numCol * 125);
          fldText = ("Page " + (numPg + 1) + " Row " + numRow + " Col " + (numCol + 1));
          fnAddRowField(doc, numPg, numRow, startX, 125, "Fld", fldText);
          }; // next Column (0 to 4)
          }; // next Row (1 to 64)

          if (howManyPages > doc.numPages) { // add page if there are more to do
          doc.newPage();
          };
          }; // next Page

          doc.saveAs({cPath: outFile}); // save the file to disk

          console.println("\nThere are " + doc.numFields + " Fields in this document");

          doc.closeDoc(true); // close the document
          doc = undefined;

          app.endPriv();
          return;
          }); // END function fnMakePDF
          • 2. Re: Memory usage Acrobat Pro using Javascript
            (Aandi_Inston) Level 1
            Acrobat is an interactive tool with some automation facilities, so
            when you try to use it for high volume automation you hit its limits
            quickly. Quitting after each file may be a must.

            25,600 form fields is likely to cause all manner of problems. I don't
            imagine the product was seriously tested with more form fields than a
            human could add in an afternoon.

            Aandi Inston
            • 3. Re: Memory usage Acrobat Pro using Javascript
              Hi: Its a bug in acrobat 8 that Adobe refuses to address. Just do a few google searches on "Acrobat 8 Memory Leak". I am also using acrobat 8 to programatically open and read bookmark titles. Thats all I am doing and I close the PDOC and null the bookmarks after every loop but Adobe keeps using ram and will never release it. After going back and forth with a few other developers on the web we all conclude that Acrobat 8 has a memory leak and Adobe does not respond to any inquiry regarding this. Most have reverted to acrobat 7 which is stable. I cannot revert so after every 100 or so loops I quit and re launch acrobat.
              • 4. Re: Memory usage Acrobat Pro using Javascript
                Patrick Leckey Level 3
                Does the same happen with Acrobat 9? It's memory management was greatly improved over 8.