我最近做了 this tutorial并让代码运行良好。然后,今天,我在 Eclipse 中重新打开项目并选择 Run As...Run on Server。从 Eclipse 控制台中运行的日志来看,该应用程序似乎经历了正常的加载过程,但是当我期望该应用程序改为在浏览器中加载时,Eclipse 控制台中出现了以下错误消息:
Exception in thread "http-bio-8080-exec-3" java.lang.OutOfMemoryError: PermGen space
我也确实运行了来自 this tutorial 的代码之前,并打开了一些 blob 文件,但我不认为这是导致问题的原因,因为即使我关闭所有内容并在执行运行方式之前重新启动计算机时此错误仍然存在...再次在服务器上运行下面的代码。
我搜索了错误和read posts关于内存泄漏,例如将大量文件完全加载到内存而不是使用输入流等。但是当我分析应用程序中的所有代码时,我找不到任何大变量。我在下面发布代码。
如何找到内存泄漏?
这是链接 Controller :
@Controller
public class LinkController {
@RequestMapping(value="/")
public ModelAndView mainPage() {return new ModelAndView("home");}
@RequestMapping(value="/index")
public ModelAndView indexPage() {return new ModelAndView("home");}
}
这是团队 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;
}
}
这是 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();
}
}
这是初始化程序:
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);
}
}
这是 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;
}
}
这是团队:
@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;}
}
这是 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();}
}
编辑
如果我应该设置 JAVA_OPTS 变量以允许类卸载并增加内存大小,我该如何在运行 Tomcat 7 的 Windows 7 中执行此操作?
我的感觉是我需要创建一个 Windows 系统变量,然后可能会在命令行上运行一些东西。但是什么?这是我的开头:
JAVA_OPTS="-XX:MaxPermSize=128M -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled -Xms256m -Xmx512m"
最佳答案
如果你想在Windows上改变你的tomcat实例的JAVA_OPTS
,你需要编辑文件catalina.bat
,通常在TOMCAT_BASE/bin/catalina .bat
.
但是,我会调整您指定的选项。首先,如果您指定-XX:+CMSClassUnloadingEnabled
,则不需要-XX:+CMSPermGenSweepingEnabled
。
其次,要使 -XX:+CMSClassUnloadingEnabled
生效,您还必须指定 -XX:+UseConcMarkSweepGC
。
因此,总而言之,编辑您的 TOMCAT_BASE/bin/catalina.bat
并在脚本开头的巨大的 rem
语句 block 下(第 99 行附近的某处) ish), 添加这一行:
set JAVA_OPTS=-XX:MaxPermSize=128M -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC -Xms256m -Xmx512m
请记住,如果您需要更多的 PermGen 空间,请将 MaxPermSize
增加到更高的值,但是不要使用垃圾收集选项(UseConcMarkSweepGC
和 CMSClassUnloadingEnabled
) 你只是在延长不可避免的 java.lang.OutOfMemoryError: PermGen space
希望对你有帮助
关于java - 在 Spring MVC 应用程序中查找内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20251800/