Memory leak detection in spring mvc application

I recently made this tutorial and got the code in order. Then, today, I reopened the project in eclipse and selected Run As ... Run on Server. It looks like the application performed its usual download process from the logs running in the eclipse console, but then the following error message appeared on the eclipse console the moment I expected the application to load in the browser:

Exception in thread "http-bio-8080-exec-3" java.lang.OutOfMemoryError: PermGen space 

I also ran the code from this guide and opened some blob files, but I don’t think I caused this problem because this error persists even when I close everything and restart the computer before starting as ... Run the code below on the server .

I searched for an error and read messages 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 large variables. I am posting the code below. Please let me know if there is anything else I should add to help you find the problem.

Can someone show me where the memory leak occurs?

Here is the link controller:

 @Controller public class LinkController { @RequestMapping(value="/") public ModelAndView mainPage() {return new ModelAndView("home");} @RequestMapping(value="/index") public ModelAndView indexPage() {return new ModelAndView("home");} } 

Here is the command controller:

 @Controller @RequestMapping(value="/team") public class TeamController { @Autowired private TeamService teamService; @RequestMapping(value="/add", method=RequestMethod.GET) public ModelAndView addTeamPage() { ModelAndView modelAndView = new ModelAndView("add-team-form"); modelAndView.addObject("team", new Team()); return modelAndView; } @RequestMapping(value="/add", method=RequestMethod.POST) public ModelAndView addingTeam(@ModelAttribute Team team) { ModelAndView modelAndView = new ModelAndView("home"); teamService.addTeam(team); String message = "Team was successfully added."; modelAndView.addObject("message", message); return modelAndView; } @RequestMapping(value="/list") public ModelAndView listOfTeams() { ModelAndView modelAndView = new ModelAndView("list-of-teams"); List<Team> teams = teamService.getTeams(); modelAndView.addObject("teams", teams); return modelAndView; } @RequestMapping(value="/edit/{id}", method=RequestMethod.GET) public ModelAndView editTeamPage(@PathVariable Integer id) { ModelAndView modelAndView = new ModelAndView("edit-team-form"); Team team = teamService.getTeam(id); modelAndView.addObject("team",team); return modelAndView; } @RequestMapping(value="/edit/{id}", method=RequestMethod.POST) public ModelAndView edditingTeam(@ModelAttribute Team team, @PathVariable Integer id) { ModelAndView modelAndView = new ModelAndView("home"); teamService.updateTeam(team); String message = "Team was successfully edited."; modelAndView.addObject("message", message); return modelAndView; } @RequestMapping(value="/delete/{id}", method=RequestMethod.GET) public ModelAndView deleteTeam(@PathVariable Integer id) { ModelAndView modelAndView = new ModelAndView("home"); teamService.deleteTeam(id); String message = "Team was successfully deleted."; modelAndView.addObject("message", message); return modelAndView; } } 

Here is TeamDAOImpl:

 @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("unchecked") public List<Team> getTeams() { return getCurrentSession().createQuery("from Team").list(); } } 

Here is the initializer:

 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("dispatcher", new DispatcherServlet(ctx)); servlet.addMapping("/"); servlet.setLoadOnStartup(1); } } 

Here is the WebAppConfig:

 @Configuration @ComponentScan("com.sprhib") @EnableWebMvc @EnableTransactionManagement @PropertySource("classpath:application.properties") public class WebAppConfig { private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver"; private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password"; private static final String PROPERTY_NAME_DATABASE_URL = "db.url"; private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username"; private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect"; private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql"; private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "entitymanager.packages.to.scan"; @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("/WEB-INF/pages/"); resolver.setSuffix(".jsp"); resolver.setViewClass(JstlView.class); return resolver; } } 

Here is the command:

 @Entity @Table(name="teams") 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;} } 

Here is TeamServiceImpl:

 @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<Team> getTeams() {return teamDAO.getTeams();} } 

EDIT:

If I have to set the JAVA_OPTS variable to allow class unloading and increase memory size, how to do it in Windows 7 working with tomcat 7?

I believe that I need to create a Windows system variable and possibly run something on the command line after. But what? Here is what I start with:

 JAVA_OPTS="-XX:MaxPermSize=128M -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled -Xms256m -Xmx512m" 
+6
source share
2 answers

If you want to change the JAVA_OPTS your tomcat instance on Windows, you need to edit the catalina.bat file usually in TOMCAT_BASE/bin/catalina.bat .

BUT, I would clarify the parameters that you specified. First, if you specify -XX:+CMSClassUnloadingEnabled , you do not need -XX:+CMSPermGenSweepingEnabled .

Secondly, for -XX:+CMSClassUnloadingEnabled , to have any effect, you must also specify -XX:+UseConcMarkSweepGC .

So, in short, edit your TOMCAT_BASE/bin/catalina.bat and under the huge block of rem statements at the beginning of the script (somewhere around line 99 ish), add this line:

 set JAVA_OPTS=-XX:MaxPermSize=128M -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC -Xms256m -Xmx512m 

And remember that if you need more PermGen space, increase MaxPermSize to something bigger, but without the garbage collection options ( UseConcMarkSweepGC and CMSClassUnloadingEnabled ) you just drag out the inevitable java.lang.OutOfMemoryError: PermGen space

Hope that helps

+5
source

You may not experience a memory leak in your application. There is a server problem that occurs when you redeploy the application multiple times, which ultimately leads to memory problems. Unfortunately, all you can do at this point is to reload everything, and your application should work fine.

Take a look at this question , which will help you increase the available memory for Java so that you can work longer before using this problem.

This question and this answer may also be helpful.

0
source

Source: https://habr.com/ru/post/958950/


All Articles