title: Finding a memory leak in a Spring MVC app
body: <p>I recently did <a href="http://fruzenshtein.com/spring-mvc-hibernate-maven-crud/" rel="nofollow noreferrer">this tutorial</a> and got the code running fine.  Then, today, I reopened the project in Eclipse and chose Run As...Run on Server.  The application seemed to go through its normal load process from the logs running in the Eclipse console, but then the following error message showed up in the Eclipse console at the point when I would have expected the application to load in the browser instead:</p>
  <pre><code>Exception in thread &quot;http-bio-8080-exec-3&quot; java.lang.OutOfMemoryError: PermGen space  
  </code></pre>
  <p>I did also run the code from <a href="http://viralpatel.net/blogs/tutorial-save-get-blob-object-spring-3-mvc-hibernate/" rel="nofollow noreferrer">this tutorial</a> beforehand, and opened a few blob files, but I don't think that caused the problem because this error persists even when I shut everything down and restart the computer before doing Run As...Run on Server for the code below again.</p>
  <p>I searched for the error and <a href="https://stackoverflow.com/questions/14988234/java-lang-outofmemoryerror">read posts</a> about memory leaks from things like loading a massive file completely into memory instead of using an input stream, etc.  But when I analyzed all the code in the application, I could not find any large variables.  I am posting the code below.</p>
  <p>How can I find the memory leak?</p>
  <p>Here is Link Controller:</p>
  <pre><code>@Controller
  public class LinkController {
      
      @RequestMapping(value=&quot;/&quot;)
      public ModelAndView mainPage() {return new ModelAndView(&quot;home&quot;);}
      
      @RequestMapping(value=&quot;/index&quot;)
      public ModelAndView indexPage() {return new ModelAndView(&quot;home&quot;);}
  
  }
  </code></pre>
  <p>Here is Team Controller:</p>
  <pre><code>@Controller
  @RequestMapping(value=&quot;/team&quot;)
  public class TeamController {
      
      @Autowired
      private TeamService teamService;
      
      @RequestMapping(value=&quot;/add&quot;, method=RequestMethod.GET)
      public ModelAndView addTeamPage() {
              ModelAndView modelAndView = new ModelAndView(&quot;add-team-form&quot;);
              modelAndView.addObject(&quot;team&quot;, new Team());
              return modelAndView;
      }
      
      @RequestMapping(value=&quot;/add&quot;, method=RequestMethod.POST)
      public ModelAndView addingTeam(@ModelAttribute Team team) {
              ModelAndView modelAndView = new ModelAndView(&quot;home&quot;);
              teamService.addTeam(team);
              String message = &quot;Team was successfully added.&quot;;
              modelAndView.addObject(&quot;message&quot;, message);
              return modelAndView;
      }
      
      @RequestMapping(value=&quot;/list&quot;)
      public ModelAndView listOfTeams() {
              ModelAndView modelAndView = new ModelAndView(&quot;list-of-teams&quot;);
              List&lt;Team&gt; teams = teamService.getTeams();
              modelAndView.addObject(&quot;teams&quot;, teams);
              return modelAndView;
      }
      
      @RequestMapping(value=&quot;/edit/{id}&quot;, method=RequestMethod.GET)
      public ModelAndView editTeamPage(@PathVariable Integer id) {
              ModelAndView modelAndView = new ModelAndView(&quot;edit-team-form&quot;);
              Team team = teamService.getTeam(id);
              modelAndView.addObject(&quot;team&quot;,team);
              return modelAndView;
      }
      
      @RequestMapping(value=&quot;/edit/{id}&quot;, method=RequestMethod.POST)
      public ModelAndView edditingTeam(@ModelAttribute Team team, @PathVariable Integer id) {
              ModelAndView modelAndView = new ModelAndView(&quot;home&quot;);       
              teamService.updateTeam(team);
              String message = &quot;Team was successfully edited.&quot;;
              modelAndView.addObject(&quot;message&quot;, message);
              return modelAndView;
      }
      
      @RequestMapping(value=&quot;/delete/{id}&quot;, method=RequestMethod.GET)
      public ModelAndView deleteTeam(@PathVariable Integer id) {
              ModelAndView modelAndView = new ModelAndView(&quot;home&quot;);
              teamService.deleteTeam(id);
              String message = &quot;Team was successfully deleted.&quot;;
              modelAndView.addObject(&quot;message&quot;, message);
              return modelAndView;
      }
  }
  </code></pre>
  <p>Here is TeamDAOImpl:</p>
  <pre><code>@Repository
  public class TeamDAOImpl implements TeamDAO {
      @Autowired
      private SessionFactory sessionFactory;
      
      private Session getCurrentSession() {return sessionFactory.getCurrentSession();}
  
      public void addTeam(Team team) {getCurrentSession().save(team);}
  
      public void updateTeam(Team team) {
              Team teamToUpdate = getTeam(team.getId());
              teamToUpdate.setName(team.getName());
              teamToUpdate.setRating(team.getRating());
              getCurrentSession().update(teamToUpdate);
      }
  
      public Team getTeam(int id) {
              Team team = (Team) getCurrentSession().get(Team.class, id);
              return team;
      }
  
      public void deleteTeam(int id) {
              Team team = getTeam(id);
              if (team != null){getCurrentSession().delete(team);}
      }
  
      @SuppressWarnings(&quot;unchecked&quot;)
      public List&lt;Team&gt; getTeams() {
              return getCurrentSession().createQuery(&quot;from Team&quot;).list();
      }
  
  }
  </code></pre>
  <p>Here is Initializer:</p>
  <pre><code>public class Initializer implements WebApplicationInitializer {
      public void onStartup(ServletContext servletContext)throws ServletException {
              AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
              ctx.register(WebAppConfig.class);
              servletContext.addListener(new ContextLoaderListener(ctx));
              ctx.setServletContext(servletContext);
              Dynamic servlet = servletContext.addServlet(&quot;dispatcher&quot;, new DispatcherServlet(ctx));
              servlet.addMapping(&quot;/&quot;);
              servlet.setLoadOnStartup(1);
      }
  }  
  </code></pre>
  <p>Here is WebAppConfig:</p>
  <pre><code>@Configuration
  @ComponentScan(&quot;com.sprhib&quot;)
  @EnableWebMvc
  @EnableTransactionManagement
  @PropertySource(&quot;classpath:application.properties&quot;)
  public class WebAppConfig {
      private static final String PROPERTY_NAME_DATABASE_DRIVER = &quot;db.driver&quot;;
      private static final String PROPERTY_NAME_DATABASE_PASSWORD = &quot;db.password&quot;;
      private static final String PROPERTY_NAME_DATABASE_URL = &quot;db.url&quot;;
      private static final String PROPERTY_NAME_DATABASE_USERNAME = &quot;db.username&quot;;
      private static final String PROPERTY_NAME_HIBERNATE_DIALECT = &quot;hibernate.dialect&quot;;
      private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = &quot;hibernate.show_sql&quot;;
      private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = &quot;entitymanager.packages.to.scan&quot;;
  
      @Resource
      private Environment env;
      
      @Bean
      public DataSource dataSource() {
              DriverManagerDataSource dataSource = new DriverManagerDataSource();
              dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
              dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
              dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
              dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));
              return dataSource;
      }
      
      @Bean
      public LocalSessionFactoryBean sessionFactory() {
              LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
              sessionFactoryBean.setDataSource(dataSource());
              sessionFactoryBean.setPackagesToScan(env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));
              sessionFactoryBean.setHibernateProperties(hibProperties());
              return sessionFactoryBean;
      }
      
      private Properties hibProperties() {
              Properties properties = new Properties();
              properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
              properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
              return properties;        
      }
      
      @Bean
      public HibernateTransactionManager transactionManager() {
              HibernateTransactionManager transactionManager = new HibernateTransactionManager();
              transactionManager.setSessionFactory(sessionFactory().getObject());
              return transactionManager;
      }
      
      @Bean
      public UrlBasedViewResolver setupViewResolver() {
              UrlBasedViewResolver resolver = new UrlBasedViewResolver();
              resolver.setPrefix(&quot;/WEB-INF/pages/&quot;);
              resolver.setSuffix(&quot;.jsp&quot;);
              resolver.setViewClass(JstlView.class);
              return resolver;
      }
  }  
  </code></pre>
  <p>Here is Team:</p>
  <pre><code>@Entity
  @Table(name=&quot;teams&quot;)
  public class Team {
      @Id
      @GeneratedValue
      private Integer id;
      private String name;
      private Integer rating;
      public Integer getId() {return id;}
      public void setId(Integer id) {this.id = id;}
      public String getName() {return name;}
      public void setName(String name) {this.name = name;}
      public Integer getRating() {return rating;}
      public void setRating(Integer rating) {this.rating = rating;}
  }  
  </code></pre>
  <p>Here is TeamServiceImpl:</p>
  <pre><code>@Service
  @Transactional
  public class TeamServiceImpl implements TeamService {
      @Autowired
      private TeamDAO teamDAO;
  
      public void addTeam(Team team) {teamDAO.addTeam(team);}
  
      public void updateTeam(Team team) {teamDAO.updateTeam(team);}
  
      public Team getTeam(int id) {return teamDAO.getTeam(id);}
  
      public void deleteTeam(int id) {teamDAO.deleteTeam(id);}
  
      public List&lt;Team&gt; getTeams() {return teamDAO.getTeams();}
  
  }  
  </code></pre>
  <h2>Edit</h2>
  <p>If I am supposed to set the JAVA_OPTS variable to allow class unloading, and to increase memory size, how do I do so in Windows 7 running Tomcat 7?</p>
  <p>My sense is I need to create a Windows system variable and possibly run something on the command line after.  But what?  Here is what I am starting with:</p>
  <pre><code>JAVA_OPTS=&quot;-XX:MaxPermSize=128M -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled -Xms256m -Xmx512m&quot;
  </code></pre>