0

I am facing error in my org. Need some suggestion how can I avoid it.

Apex heap size too large:

Here is my code:

global class OutputFileBatch implements Database.Batchable<sObject>, Database.Stateful{
    public Call_Plan_SCenario__c callPlanScenario{get;set;}
    public List<String> lstOfObjects ;
    public string[] fields;
    public string db_ObjectName;
    public Integer counter;
    public String str;
    public string nameOfFile;
    Output_File__c outputFile=new Output_File__c();

    public OutputFileBatch(Call_Plan_SCenario__c newObj,String objectName,Integer count){
         callPlanScenario=newObj;
         lstOfObjects = new List<String>();
         db_ObjectName = objectName;
         counter = count;
         nameOfFile = db_ObjectName;
        nameOfFile = nameOfFile.substring(0,nameOfFile.length()-3);

        outputFile.Name=nameOfFile;
        outputFile.Scenario_Id__c=callPlanScenario.Id;
        insert outputFile; 
        system.debug('db_ObjectName-->'+db_ObjectName);
    }

    global Database.QueryLocator start(Database.BatchableContext BC){

       str=Utilities.GetHeaders(db_ObjectName)+'\r\n';
       string[] fields=Utilities.GetQuery(db_ObjectName );
       String query = 'select '+ String.join(fields, ',') +' from '+ db_ObjectName;
       return database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<sobject> scope){

             system.debug('--Limits.getLimitHeapSize()-->'+Limits.getLimitHeapSize());
             system.debug('--Limits.getHeapSize-->'+Limits.getHeapSize());
               for(sObject rec : scope){
                  str+=Utilities.GetRecord(rec,db_ObjectName);
                }
                scope.clear();

    }

    global void finish(Database.BatchableContext BC){
                Attachment myAttachment = new Attachment();
                myAttachment.Body = Blob.valueOf( str );
                myAttachment.Name = nameOfFile +'.txt';
                myAttachment.ParentId = outputFile.Id; 
                myAttachment.ContentType = 'text/csv';
                insert myAttachment;

     }    
}
3

Looks like your goal is to create a giant string that represents all the fields of all the records of an object. Whatever you do in the peripheral code, that string will grow to consume all the heap (if it doesn't hit the 6,000,000 character string length limit first) if you have a large number of records (and made worse if you large amounts of data per record). Attachment bodies also have size limits.

I suggest change to chaining a series of these batchables where each one handles a limited number of records and creates its own attachment.

| improve this answer | |
  • Yes I am attaching records more than 1 lakh. My user wants only one attachment for this big file. File would be around 15 mb. Can you give another suggestion how can I process further. For a while I am passing a single object in my parameter that contains records more than 1 lakh – Jill_sfdc Feb 28 '17 at 12:12
  • 1
    @Jill_sfdc What your user wants may not be possible so you may have no choice but to re-negotiate the requirement. – Keith C Feb 28 '17 at 12:17
1

Heap is generally caused by querying too many objects, creating too many objects, or storing too much state.

One common example we have is we wrap SObjects with our own classes when calling our services. This means, when a user calls our "retrieve" method to retrieve, say, Projects, we query for all the Project__c records, then for each Project__c we create a new Project(). That means we essentially double up heap for each record.

Another example is querying related fields. For example, if your query says [SELECT Id, Account__r.Name FROM Project__c], each Project__c record will have it's own copy of the Account__c object. If you have 100 projects with a related account, and 2 accounts, you'll have 98 duplicates, so 98 records taking up heap.

If, instead, you query for [SELECT Id, Account__c FROM Project__c], as well as [SELECT Id, Name FROM Account__c WHERE Id IN (SELECT Account__c FROM Project__c)], then that's an extra SOQL, but significantly less heap.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.