LINUX.ORG.RU

Ява посасывает...

 , ,


0

2

Яву знаю очень плохо, но решил написать на ней бота для сайта знакомств, дак вот, написал, работает, но при обходе 110 и больше девушек, валится ошибкой переполнения памяти «OutOfMemoryError», да-да, я тот криворукий, кто умудрился в яве со сборщиком мусора допустить течку памяти. Где посасывает и кто, не понимаю. Будды явы, посмотрите код, скажите где допущены косяки...


Полная ошибка выглядит так:

Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
	at java.util.Arrays.copyOfRange(Unknown Source)
	at java.lang.String.<init>(Unknown Source)
	at net.sourceforge.htmlunit.corejs.javascript.TokenStream.getStringFromBuffer(TokenStream.java:1418)
	at net.sourceforge.htmlunit.corejs.javascript.TokenStream.getToken(TokenStream.java:544)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.peekToken(Parser.java:331)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.nextToken(Parser.java:370)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.propertyAccess(Parser.java:2744)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.memberExprTail(Parser.java:2639)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.memberExpr(Parser.java:2614)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.unaryExpr(Parser.java:2476)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.mulExpr(Parser.java:2401)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.addExpr(Parser.java:2385)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.shiftExpr(Parser.java:2366)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.relExpr(Parser.java:2341)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.eqExpr(Parser.java:2313)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.bitAndExpr(Parser.java:2302)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.bitXorExpr(Parser.java:2291)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.bitOrExpr(Parser.java:2280)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.andExpr(Parser.java:2269)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.orExpr(Parser.java:2258)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.condExpr(Parser.java:2222)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.assignExpr(Parser.java:2185)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.expr(Parser.java:2164)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.statementHelper(Parser.java:1183)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.statement(Parser.java:1045)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.parseFunctionBody(Parser.java:687)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.function(Parser.java:852)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.primaryExpr(Parser.java:2941)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.memberExpr(Parser.java:2578)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.unaryExpr(Parser.java:2476)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.mulExpr(Parser.java:2401)
	at net.sourceforge.htmlunit.corejs.javascript.Parser.addExpr(Parser.java:2385)

shiva ()

Когда найдёшь девушку — не показывай эй этот код. Ибо не даст.

P. S. Лучше пиши на Haskell. У программистов на Haskell не случается OOME и, как следствие, им все дают.

Bass ★★ ()
Ответ на: комментарий от shiva

Когда OOM проблема сложнее локализовать так как stacktrace не указывает на конкретный код и часто с каждым крешем stacktrace меняется. Стектрейc выше похож на парсер html или xpath, но виновником может быть не он. В коде много плохо оптимизированных мест, saveGirl в цикле сохраняет в один и тот же файл? Значит можно было 1 раз открыть перед циклом и закрыть в конце. Мало того он 100 раз создает StringBuilder и складывает путь файла в строку)

kazufukurou ()
Ответ на: комментарий от kazufukurou

Отключил выполнение методов savegirl и checkgirl, но проблема все та же, текет где-то тут:

for (int i = 0; i < maxgirl; i++)
	{
		TimeUnit.SECONDS.sleep(2);		
		HtmlAnchor link3 = (HtmlAnchor)p1.getByXPath("//a[@target='_blank']").get(0);
		HtmlPage p3 = link3.click();
		//if ( checkGirl(fpath+city+".txt",p3.getUrl().toString()) == false) {
		if (true) {
			TimeUnit.SECONDS.sleep(5);
		WebRequest nextmessS = new WebRequest(new URL(p3.getUrl().toString()), HttpMethod.POST);
		ArrayList<NameValuePair> nextmessP = new  ArrayList<NameValuePair>();
		nextmessP.add(new NameValuePair("js","off"));
		nextmessP.add(new NameValuePair("action","post"));
		nextmessP.add(new NameValuePair("dopost","1"));
		nextmessP.add(new NameValuePair("message",initialmessage));
		nextmessS.setCharset(Charset.forName("windows-1251"));
		nextmessS.setRequestParameters(nextmessP);
		System.out.println("\n["+String.valueOf(i)+"] Отправка сообщения девушке: "+p3.getUrl().toString()+" "+webClient.loadWebResponse(nextmessS).getStatusMessage());
		//saveGirl(fpath+city+".txt",p3.getUrl().toString()+"\n");
		}
		else {
			System.out.println("\n["+String.valueOf(i)+"] Есть...");
			}
		p1 = p1.getAnchorByText("следующая").click();
		//System.gc();
		
	}

shiva ()

вебклиент - вот твоя проблема. Он скорее всего собирает все ответы в хип и так и живет, GC не приходит.

Делай его удаление раз в N итераций и создавай новый.

anonymous ()
Ответ на: комментарий от Jefail

Единственный, кто здесь посасывает - это ты

Не посасываю а глотаю глубокой глоткой в данном случае, тем не менее, в стартпосте есть уточнение, что с явой знаком поверхностно.

shiva ()

Если будешь много раз пытаться запускать против настоящего сервера, тебя могут заблочить по ip за рекурсивную скачку. Причины «течки» я не увидел, может какой объект из подключенный либы держит цепочку объектов и они не попадают под GC, на самом деле разобраться не сложно, нужно только стандартный профайлер из поставки jdk научится использовать - jvisualvm, там делаешь снимок кучи в момент запуска, ближе к падению, а дальше смотришь объекты в дампе, каких объектов много, кто на них держит ссылки.

Единственное замечание, в saveGirl ты делай close в блоке finally, иначе после принудительного завершения приложения, будет открыт дескриптор доступа к файлу, в виндовой fs это вообще лок на файл. Против всех видов I/O нужно делать так:

try{ ... } catch (Excetpion e) {...} finally { io.close() }

Aber ()
Ответ на: комментарий от ritsufag

ищу постоянную девушку для секса, анонимность гарантирую
анонимность

Это каким образом? Он будет входить в неё посредством ssl не оставляя после себя куки авторизации? :D

linux-org-ru ()

Наверное не сработает, но чисто ради прикола можно сделать так:

nextPage = p1.getAnchorByText("следующая").click();
p1 = null;
System.gc();
p1 = nextPage;
Но это если GC тупит (мне однажды приходилось что-то такое делал в JUnit), а если утечка в самой либе com.gargoylesoftware, то не поможет.

Aber ()

Посмотри содержимое click(); когда сдается новая страница ей наверное переделается ссылка на старую, вот тебе и утечка памяти.

Aber ()
Ответ на: комментарий от Bass

У программистов на Haskell не случается OOME

Prelude> import qualified Data.ByteString as B
Prelude B> B.length $ B.replicate (10^12) 0
Loading package bytestring-0.9.2.1 ... linking ... done.
<interactive>: out of memory (requested 1000000716800 bytes)
monk ★★★★★ ()

initialmessage надо переписать на что-то вроде:

static string initialmessage = "Здравствуйте. Ищу девушку для совместного изучения языка Java, возможно даже и Haskell.";

vasyan ()

У них в доках, написано про вызов WebClient.close как единственное решение. Видимо этот HtmlPage где то внутри кэшируется и поэтому гс не удаляет его. Видимо это баг. Нужно читать исходники.
Поэтому создавай вебклиента, делай необходимые действия(до исключения) и закрывай клиента. Если много обработки разбить на такие вот подзадачи.

tyamur ()

Добавь аргумент для VM: -Xmx2G или можно больше, в зависимости от размера твоей оперативки. Если запускаешь в Eclipse, то это где-то в разделе Run configurations...

А лучше запусти Chrome в headless mode, он стабильнее и памяти будет меньше жрать. А HtmlUnit, то еще поделие.

P.S. И чо, реально думаешь это сработает «Привет, ищу постоянную девушку для секса, анонимность гарантирую.»? Хотя если в Москве или еще в каком довольно крупном городе... Нарвёшься на какую-нибудь черную вдову...

foror ★★★ ()

Будды явы, посмотрите код, скажите где допущены косяки...

Советую медитировать, ходить в православный храм, молиться, думать о смысле жизни, о том, чего же вы желаете достичь и успеть в жизни...

anonymous ()
                        while ((s = lnr.readLine()) != null) {

				if (s.compareTo(girl) == 0)
					check = true;

			}

Ну, а теперь подумайте, как это сделать правильно и красиво.

shiva

А то ведь IRL за «индусский код»(TM) и уволить могут.

Bioreactor ★★★★★ ()
Последнее исправление: Bioreactor (всего исправлений: 1)

Вынеси объявление объектов перед циклом «for»

HtmlAnchor link3 HtmlPage p3 WebRequest nextmessS ArrayList<NameValuePair> nextmessP

После обработки «p3» после закрытия if - сделай что нибудь с ним на всякий случай, думаю там есть что-то типа close() или что-то в этом роде, хотя и так вроде должно будет полегчать.

Serg_HIS ()