[SNMP4J] Memory Leak in SNMP4J Agent

robert.m.dabell at L-3com.com robert.m.dabell at L-3com.com
Fri Aug 19 01:46:11 CEST 2005


I have a SNMP manager that is querying data from a modified SNMP4J
TestAgent.  I left it running over night and when I returned the Heap had
run out of memory for the Agent.  Today, I ran a little test to see if I
could repeat the problem and using JConsole, I have noticed that the memory
usage of the agent keeps growing while messages are being sent and doesn't
recover the memory when the manager stops.  

Using the -Dcom.sun.management.jmxremote option with the TestAgent (i.e.
java -Dcom.sun.management.jmxremote -cp snmp4j-agent.jar
org.snmp4j.agent.test.TestAgent), run JConsole (included with JDK 1.5) and
run the following code, which will send a GET sysUpTime PDU as fast as it is
receives the previous request's response.  On the JConsole you will see an
increase in memory usage and it will not decrease when the Manager is
shutdown.  The TestAgent also dies after about 8 1/2 minutes with the Out of
memory exception (default 64M heap).  All I am doing with this test is
reading one variable over and over.  Memory shouldn't be an issue.

import java.io.IOException;

import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.event.ResponseListener;
import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.MessageProcessingModel;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.SecurityModels;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.security.USM;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.Variable;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;


public class TestManager{
  private Snmp snmp;
  
  public TestManager(String host, int port){
    try {
      Address address = GenericAddress.parse("udp:"+host+"/"+port);
      System.out.println("Address = " + address);
      
      
      TransportMapping transport = new DefaultUdpTransportMapping();
      snmp = new Snmp(transport);
      transport.listen();

      MessageProcessingModel mp =
snmp.getMessageProcessingModel(MessageProcessingModel.MPv2c);
      
      
      USM usm = new USM(SecurityProtocols.getInstance(), new
OctetString(MPv3.createLocalEngineID()), 0);
      SecurityModels.getInstance().addSecurityModel(usm);
      
      
      
      CommunityTarget target = new CommunityTarget();
      
      
      target.setCommunity(new OctetString("public"));
        
            
      target.setAddress(address);
      target.setRetries(1);
      target.setTimeout(100);
      target.setVersion(SnmpConstants.version2c);
      
      
      while(true){
        PDU pdu = new PDU();
        pdu.setType(PDU.GET);
        VariableBinding varbind = new
VariableBinding(SnmpConstants.sysUpTime);
        pdu.add(varbind);
        synchronized(snmp){
          snmp.send(pdu, target,null, listener);
        
          try {
            snmp.wait();
          } catch (InterruptedException e) {
           
            e.printStackTrace();
          }
        }
      }
     
    } catch (IOException e) {
      
      e.printStackTrace();
    }
   
    
  }
  
  private ResponseListener listener = new ResponseListener(){
    VariableBinding varbind = null;
    Variable var = null;
    Object value = null;
  
    public void onResponse(ResponseEvent event) {
      // Always cancel async request when response has been received
      // otherwise a memory leak is created! Not canceling a request
      // immediately can be useful when sending a request to a broadcast
      // address.
      ((Snmp)event.getSource()).cancel(event.getRequest(), this);
      System.out.println("Received response PDU is: "+event.getResponse());
      
      PDU rpdu = event.getResponse();
      
      
      if (rpdu != null){
        varbind = rpdu.get(0);
        OID oid = varbind.getOid();
        if (oid.equals(SnmpConstants.sysUpTime)){
          var = varbind.getVariable();
          System.out.println("uptime = " + var);
        }
        
      } else {
        System.out.println("PDU timed out");
      }
      synchronized(snmp){
        snmp.notifyAll();
      }
      
      
    }
  };
  
  
  
  public static void main(String[] args) {
    new TestManager(args[0], Integer.parseInt(args[1]));
  }

}


This test manager is extreme as far as frequency of requests are concerned
but the application that I am implementing would only have 1 hr run time
before the agent runs out of memory and stops working.



R. Mark DaBell




More information about the SNMP4J mailing list