Почему этот объект env продолжает расти в размере?
Я работаю над веб-сканером уже некоторое время, идея проста, у меня есть таблица SQL, содержащая список веб-сайтов, у меня много потоков, которые выбирают первый веб-сайт из таблицы и удаляют его, а затем сканируют (в куча как манера).
Код слишком длинный, поэтому я попытаюсь удалить некоторые его части:
while(true){
if(!stopped){
System.gc();
Statement stmt;
String scanned = "scanned";
if (!scan)scanned = "crawled";
Connection connection = null;
try {
connection = Utils.getConnection();
} catch (Exception e1) {
connection.close();
e1.printStackTrace();
}
String name;
stmt = connection.createStatement();
ResultSet rs = null;
boolean next;
do {
rs = stmt.executeQuery("select url from websites where "+scanned+" = -1");
next = rs.next();
} while (next && Utils.inBlackList(rs.getString(1)));
if(next){
name = rs.getString(1);
stmt.executeUpdate("UPDATE websites SET "+scanned+" = 1 where url = '"+Utils.stripDomainName(name)+"'");
String backup_name = name;
name = Utils.checkUrl(name);
System.out.println(scanned + " of the website : " + name +" just started by the Thread : " + num);
// And here is the important part, I think
CrawlConfig config = new CrawlConfig();
String ts = Utils.getTime();
SecureRandom random = new SecureRandom();
String SessionId = new BigInteger(130, random).toString(32);
String crawlStorageFolder = "tmp/temp_storageadmin"+SessionId;
config.setCrawlStorageFolder(crawlStorageFolder);
config.setPolitenessDelay(Main.POLITENESS_DELAY);
config.setMaxDepthOfCrawling(Main.MAX_DEPTH_OF_CRAWLING);
config.setMaxPagesToFetch(Main.MAX_PAGES_TO_FETCH);
config.setResumableCrawling(Main.RESUMABLE_CRAWLING);
int numberOfCrawlers = Main.NUMBER_OF_CRAWLERS;
PageFetcher pageFetcher = new PageFetcher(config);
RobotstxtConfig robotstxtConfig = new RobotstxtConfig();
RobotstxtServer robotstxtServer = new RobotstxtServer(robotstxtConfig, pageFetcher);
try {
controller = new CrawlerController(config, pageFetcher, robotstxtServer);
controller.addSeed(name);
controller.setSeeed(name);
controller.setTimestamp(ts);
controller.setSessiiid("admin"+num+scan);
//Main.crawls.addCrawl("admin"+num+scan, new Crawl(name,"admin"+num+scan,ts));
stmt.executeUpdate("DELETE FROM tempCrawl WHERE SessionID = '"+"admin"+num+scan+"'");
if (!scan){
// Main.crawls.getCrawl("admin"+num+scan).setCrawl(true);
stmt.executeUpdate("INSERT INTO tempCrawl (SessionID, url, ts, done, crawledpages, misspelled, english, proper, scan, crawl )"
+ " VALUES ( '"+"admin"+num+scan+"', '"+name+"', '"+ts+"', false, 0, 0, true, false, "+false+" , "+true+" )");
}else{
//Main.crawls.getCrawl("admin"+num+scan).setScan(true);
stmt.executeUpdate("INSERT INTO tempCrawl (SessionID, url, ts, done, crawledpages, misspelled, english, proper, scan, crawl )"
+ " VALUES ( '"+"admin"+num+scan+"', '"+name+"', '"+ts+"', false, 0, 0, true, false, "+true+" , "+false+" )");
}
connection.close();
controller.start_auto(Crawler.class, numberOfCrawlers, false, scan,num);
} catch(Exception e){
rs.close();
connection.close();
e.printStackTrace();
}
}else{
rs.close();
connection.close();
}
//CrawlerController.start_auto(scan, num);
if (stopping){
stopped = true;
stopping = false;
}
}}
} catch (Exception e) {
e.printStackTrace();
}
Как видите, каждый раз я создаю crawlerController, сканирую веб-сайт и так далее.
Проблема в том, что размер кучи памяти jvm значительно увеличивается. После профилирования приложения с использованием профилировщика Java yourKit я обнаружил утечку памяти в следующих строках кода:
скриншот профилирования yourKit
Теперь это точная строка, с которой начинается утечка памяти, эта переменная env, кажется, занимает слишком много места и продолжает увеличиваться после каждой операции, тогда как операции независимы.
Environment env = new Environment(envHome, envConfig);
Я действительно не знаю, что делает эта переменная, и как я мог это исправить, еще одна вещь, я изменил исходный код crawlController, я подумал, что это может быть актуально.
1 ответ
Предполагая, что вы используете crawler4j
как ползучий каркас.
Каждый раз, когда вы создаете crawl controller
вы создаете новый экземпляр frontier
, который совместно используется потоками искателя для управления очередью URL-адресов для сканирования. Кроме того, создается так называемый docIdServer, который отвечает за управление, если входящий URL-адрес (например, веб-сайт) уже был обработан в этом обходе.
это frontier
и docIdServer
основаны на базе данных в памяти, в которой среда отвечает за кэширование, блокировку, ведение журнала и транзакции. По этой причине эта переменная будет расти со временем.
Если вы установите возобновляемое сканирование на true
база данных будет работать в файловом режиме и там будет расти медленнее.