Привет! Мы тут собрали тусовку одних из самых крутых русскоязычных Java-практиков и попросили их дать по задаче, чтобы вы сломали зубы, мозг и бились об стену, пытаясь понять, как это работает. Собственно, мы поспорили на бутылку Хеннеси, что за 12 часов после публикации никто не пришлёт все правильные ответы. Я уверен, что кто-то сможет. Поэтому если вы это сделаете первым – с меня бутылка.
Первая задача простая, она от телезрителя Николая Гарбузова, специалиста по скалкам, любящего рекурсию, паттерн-матчинг и магию компиляции:
Скомпилируется ли следующий аспект AJC компилятором?
Если да — то что он выведет на консоль при компиляции?
public aspect QuizAspect { public static int count(int i) { return i++; } before (int n) : execution(public int QuizAspect.count(int)) && args(n) && if(QuizAspect.count(1)>1) { System.out.println("QuizAspect " + n); } }
Пока просто, правда?
Вторая задача от Владимира Ситникова (NetCracker), грязного извращенца во всём, что касается регулярных выражений. Этот нехороший человек даже анонс своего доклада на JPoint написал с их помощью.
В чём подвох удалять Java-комментарии таким выражением? Укажите 3 причины, почему так делать нельзя. (считаем, что исходник написан нормальными символами) —Pattern.compile("/\\*(?:[^*]|\\*[^/])*\\*/")
И сразу вторая задача — можно ли написать «hello world» на java без единого пробела?
Третью задачу прислал телезритель Николай Алименков из клуба анонимных разработчиков. 10 лет он пилит свои масштабируемые системы, а к нам пришёл отдохнуть, поэтому задача одна из самых простых:
Есть 2 Spring контекста:
1. a.xml с бином
<util:list id="myList"> <value>3</value> <value>4</value> </util:list>
2. b.xml с бином
<util:list id="myList"> <value>6</value> </util:list>
Что напечатает такой фрагмент кода:
System.out.println(new ClassPathXmlApplicationContext("a.xml", "b.xml").getBean("myList"));
И как можно заставить его бросить ошибку, не изменяя логику работы кода?
Четвёртая задача предоставлена Никитой Сальников-Тарновским, конкретно упоровшимся по хардкору и написавшим инструмент для поиска утечек памяти – Plumbr. Писал не один, конечно, но прочитать полученный код может только он. Долбанный оптимизатор.
Ниже приведены 2 программы. Каждая из них пытается аллоцировать суммарно памяти больше размера хипа. Но одна из них выкидывает java.lang.OutOfMemoryError, а вторая нет. Почему?
public class OOM1 { private static final int SIZE = (int) (Runtime.getRuntime().maxMemory() * 0.55); public static void main(String[] args) { { byte[] bytes = new byte[SIZE]; System.out.println(bytes.length); } byte[] bytes1 = new byte[SIZE]; System.out.println(bytes1.length); System.out.println("I allocated memory successfully"); } } public class OOM2 { private static final int SIZE = (int) (Runtime.getRuntime().maxMemory() * 0.35); public static void main(String[] args) { { byte[] bytes = new byte[SIZE]; System.out.println(bytes.length); } byte[] bytes1 = new byte[SIZE]; System.out.println(bytes1.length); byte[] bytes2 = new byte[SIZE]; System.out.println(bytes2.length); System.out.println("I allocated memory successfully"); } }
Предпоследняя задача от Баруха Садогурского из JFrog и тусовки Bintray/Artifactory
Что выведет этот код?
def back = 'back' def quotes = ["I'll be $back", "I'll be ${-> back}", "I'll be ${back}", "I'll be "+back] println quotes back = 'bach' println quotes
Последняя – от Евгения Борисова, тренера офицеров израильской армии по Java. Spring:
Есть два бина:
@Component public class Няня { public void closeAll() { while (ребёнокГрязный()) { купайРебёнка(); } } } @Component public class Уборщица { public void closeAll() { while (посудаГрязная()) { мойПосуду(); } } }
Как сделать, чтобы при закрытия контекста, оба метода closeAll работали параллельно (и какие есть варианты)?
Ачивки и решения
- Небольшой сувенир первому, кто запостит три правильных решения под спойлер в комментарии.
- Бутылка Хеннеси – тому, кто сможет за 12 часов правильно ответить на все вопросы за один раз. Если таких будет несколько – первому, приславшему правильные ответы.
- Бесплатные билеты для вас и друга на конференцию JPoint в понедельник тому, кто сможет поправить или существенно доуточнить ответы тех, кто задавал задачи.
Ответы, пожалуйста, в комментарии под спойлер. Если вы не можете комментировать, то делайте #jpoint в Facebook или ВКонтакте.
Вот ответы на первые четыре вопроса, а после JPoint мы опубликуем и ответы на вопросы jbaruch и EvgenyBorisov.
P.S.: подсказки можно поискать в анонсах соответствующих докладов на сайте JPoint.
jbaruch
Правильные ответы 23derevo выложит не все.
Поскольку и задачка по Груви от меня и задачка по Спрингу от Борисова являются неотъемлемой частью наших докладов, за правильными ответами на них придется посетить наши доклады.
tolkkv
Т.е на них ответы сюда не писать лучше? А то некрасиво получится)
23derevo Автор
Пишите все, но под спойлер!
tolkkv
Барух что то слишком простую задачку приложил) jbaruch, самые крутые на JPoint оставил?
jbaruch
Ты тут не умничай!
gurinderu
Простую и не на Java. Несносный groovyист.
jbaruch
И не говори. Что за люди?!
jbaruch
Пиши под спойлер, и мы никому не скажем, что ты прав :)
tolkkv
Ну а чего писать ) И так же ясно что
jbaruch
SerCe
А почему так, вкратце описано на относительно новом няшном груви-сайте
Ну в а сорцах, в groovy.lang.GString#writeTo можно посмотреть что будет, если там будет кложур, принимащий одну переменую
jbaruch
Прям ваще.
tolkkv
Да сразу понятно же чем троллить будешь! В этом и беда)
jbaruch
Ну, это тебе понятно. Ты не забывай, это идет на jpoint, не на какой нибудь g8conf.
23derevo Автор
Все, но ваши — после конфы :)
AlexanderYastrebov
Encircled
Написать Hello world без пробелов можно с помощью
System.out.println("Hello"+(char)32+"World");
lany
Ваш Hello world не компилируется.
Encircled
AlexanderYastrebov
cheremin
Я могу предположить, что есть некоторое количество слотов на стеке, ниже которого нет смысла оптимизировать (тем более, что main вызывается лишь однажды, поэтому о реальной оптимизации C1/C2 речь, скорее всего, не идет — почти наверняка тут мы работаем в интерпретируемом режиме). Методом научного тыка можно обнаружить, что вот такой код
выполняется без ошибок. В то время, как вот такой
Падает с OOM.
Отсюда можно предположить, что на моей версии джавы (1.6.0_45), во видимому, два последних (то есть последних используемых) слота на стеке java не трогает, но если их становится больше, то делаются какие-то попытки переиспользовать предыдущие.
P.S. Любопытно, что вот такой код
Падает с OOM, но если заменить a= 0; на a=args.length — то выполняется успешно. Опять же, можно предположить, что константная переменная просто заменяется на свое значение, без реального размещения ее на стеке, а переменная с хоть сколь либо динамическим значением все-таки размещается — и вытесняет со стека размещенный там byte[]
23derevo Автор
грязный, грязный извращенец!
cheremin
Ну интересно же было разобраться! А потом уж что, сидеть на этом знании как Кащей над злате? ;)
gvsmirnov
К слову, если добавить достаточно циклов, чтобы ворвался компилятор, тоже много чего интересного начинается ;)
gvsmirnov
Ну и вот ещё: twitter.com/shipilev/status/588628367253057536
23derevo Автор
а мы с Лёшей сейчас это обсудим!
lany
Конечно, реклама для лохов, но Лёшу зачем с «будущим Java» вместе поставили? Придётся, видимо, Лёшей пожертвовать в угоду будущему.
23derevo Автор
когда программа хорошая (а она хорошая!), все время кто-то интересный тебе идет параллельно с кем-то другим, тоже интересным.
Скажи лучше, есть ли слоты, в которые тебе не на что пойти?
lany
На 13:50-14:40 я бы всем пожертвовал. Можно про профилирование послушать, но опционально. Скорее всего пойду в экспертную зону №1, может, там полезнее будет.
На 12:50-13:40 в принципе можно бы было всё пропустить, если б было что-то из вечерних докладов в параллели (Куксенко или Чуйко, например: оба интересны и тоже одновременно идут). Катехизис прекрасен, я не спорю, но я смотрел его на ютюбе и Алексей пишет, что будет почти то же самое. А «Сжимай меня полностью», как я понимаю, новый доклад (поправьте, если ошибаюсь), его жалко. Возможно, Фолькера послушаю. Ну или уж Алексея уважу, если места хватит :-)
И да, на 10:30-11:20 я бы тоже пропустил, если б в параллель шёл почти любой из остальных докладов :-)
23derevo Автор
ты как-то очень сложно все расписал: "… я бы пропустил, если б… ". Я в итоге ничего не понял :)
jbaruch
легче написать на что ты хочешь пойти. Потому что по комментарию похоже, что ты готов не пойти никуда.
lany
Ага, а деньги я печатаю, и мне ничего не стоит прилететь из Новосиба в Москву и оплатить участие ради того, чтобы пойти никуда =)
Если интересно, то вот куда я хочу в порядке убывания приоритета:
Если бы эти семь не пересекались, я был бы счастлив. Дальше так:
Твои доклады в топ-14 не попали, извиняй =)
jbaruch
всё ок, мне достаточно того, что они у меня получаются лучшими докладами всех jpoint и joker конференций. Но не для всех, да :-)
jbaruch
вон, 23derevo их тоже не любит :-)
23derevo Автор
я их обожаю!
cheremin
Ну да, я сначала тоже с циклами начал экспериментировать. Но там слишком много вариантов получается — и чтобы их грокнуть, чтобы построить какую-то вменяемую модель, нужно было лезть в дизасм или исходники JVM. А мне лень — я хотел простое объяснение для конкретного примера. Потому что общая идея что ссылка живет не до завершения метода, а насколько JVM мозгов хватит — она давно известна, как раз из дискуссий по ранней финализации, на которую Алексей ссылается. И вопрос был лишь в том, чем два отличаются от трех. И — неожиданно — оказалось, что два отличаются от трех ровно на один.
gvsmirnov
Ты, кстати, осчастливишь нас своим присутствием, наконец?
23derevo Автор
присоединяюсь к вопросу
cheremin
Увы, но нет. Зато придут люди из моей команды
jbaruch
Пичалька.
gvsmirnov
Грустняшка.
23derevo Автор
пиняшка!
vladimir_dolzhenko
Кто именно и с каким докладом?
cheremin
Послушать, Володя, просто послушать )
cheremin
будем немного расстроены результатом.
P.S. Вместо пробела можно использовать unicode escape типа \uXXXX, например.
SerCe
astudent
У Вас по Java только 1 задача, остальные имеют к языку лишь опосредованное отношение.
23derevo Автор
К языку да, к платформе — нет.
Но вообще сейчас разбавим, ага!
red1ynx
jbaruch
данунеможетбыть!
tolkkv
мояджавасъелаейнорм
SerCe
Всегда можно написать свой BeanPostProcessor, который будет разруливать такие ситуации
Ikryanov
23derevo Автор
окей, тогда почему обе бросают?
lany
Давайте считать, что для 32-битной JVM предполагается запускать её с опцией -server.
elDraco
Второй — использовать ApplicationEventMulticaster (например, SimpleApplicationEventMulticaster) с соответствующим taskExecutor (например, ThreadPoolExecutor) и повесить обоих на ContextCloseEvent.
В теории оба варианта должны сработать)
jbaruch
Ты крут!