Обновить
170
0
Андрей @apangin

Пользователь

Отправить сообщение
Не экземпляр класса создать, а сам класс такой, что Class.getDeclaredConstructors() вернёт для него пустой массив.
ее предлагал Даг Ли: если количество параллелизуемой работы в общем случае превышает 100 миллисекунд

А я вот тут наткнулся на то, что Даг Ли писал про 100 микросекунд.
Хотя оценка, данная Сергеем, мне кажется более реалистичной.
Поймать этот баг в продакшне ещё постараться надо. Опять же, нам «повезло» лишь благодаря высоким нагрузкам: сервер только поднимается, а на него сразу тысяча одновременных запросов прилетает с участием разных классов: RegularImmutableList, SingletonImmutableList и т.д., и все они начинают конкурентно инициализироваться. Много ли где такое встречается?
Проверил — не находит. Вот, вызов Thread.start() из статического инициализатора FindBugs считает ошибкой, а просто создание дочернего объекта — нет.

Все ошибаются, ничего позорного в этом нет. Коллегам из Google, на самом деле, респект, что отнеслись с пониманием и оперативно исправили.
Штатные есть. Хороших нет.
Стандартная сериализация 1) медленная, 2) неэкономная, 3) не справляется с эволюцией классов.
Persistence, RPC и всё остальное, где нужно преобразовывать/восстанавливать объекты.
Как вариант ещё Unsafe.allocateInstance.
Тоже не вызывает конструктор, причём безо всякой кодогенерации.
Является JVM интринсиком, то есть, инлайнится на «ура».
Угу. Рассказывал про это несколько лет назад: habrahabr.ru/post/132703/
И на StackOverflow было.
Есть еще одна особенность таких «неправильных» компараторов.
Код, который нормально работал на Java 6, может внезапно начать падать на Java 7 c
java.lang.IllegalArgumentException: Comparison method violates its general contract!

в связи с тем, что в Java 7 поменялся алгоритм, лежащий в основе Arrays.sort / Collections.sort.
Как сказать…
Вот, например, до сих пор неисправленный: JDK-8043740
Еще один относительно свежий: JDK-7019078
Ну и, конечно, печально знаменитая уязвимость.
Если бы было всё так просто! Первый же Exception сломает весь пул.
Чтобы всё работало правильно, придётся делать обёртки над Connection и Statement, которые ловят исключения и инвалидируют (закрывают) Connection, не кладя его обратно в пул. Вдобавок нужно ограничивать размер пула, а новые соединения открывать вне synchronized, чтобы избежать нежелательных задержек в многопоточном приложении.
«Когда кажется, надо смотреть в сорцы» © мой коллега :)
Нет там Reflection в рантайме. Динамическая генерация байткода + Instrumentation.retransformClasses
Совсем разные вещи.
Интринсики — часть JVM, их пишут компиляторщики. По сути, это переписывание тела метода на суровом хотспотовском IR.
JavaCritical — оптимизация для библиотек. Чтобы код на C, написанный не JVM разработчиками, эффективней вызывался.
Посмотрите, как выглядит хоть один интринсик, например, LibraryCallKit::string_indexOf, и всё станет сразу ясно.
Для native методов JIT-компилятор генерирует обёртки. Т.е. вся описанная процедура (создание фрейма, перекладывание аргументов, проверка safepoint и т.д.) происходит в динамически скомпилированном коде под данный конкретный метод. Но непосредственно с нативной реализацией метода, которая уже и так в бинарном виде, JIT, естественно, ничего сделать не может и просто вызывает, как есть.
Причины есть. Раз уж даже консервативные разработчики JVM это реализовали.
Не всё можно сделать в Java. Например, вы никак не заставите JIT-компилятор использовать SIMD. Но при этом и native не будет выигрывать, поскольку вся выгода уйдет на JNI-обертки.
— Не поддерживаются TCP опции: TCP_DEFER_ACCEPT, TCP_CORK и т.п.
— Не поддерживаются флаги send и recv: MSG_MORE, MSG_PEEK…
— Selector глючный и не потокобезопасный.
— Нельзя делеать select() на блокирующих сокетах.
— setSoTimeout не работает на SocketChannel'ах.
Да и по производительности можно выжать больше.
Меня больше интересует сколько времени эти вызовы занимают по сравнению со временем работы самого алгоритма.
Так из графиков же видно. Сравните arrayElementsCritical (стандартный JNI) с javaCritical: делают они одно и то же, значит, вся разница — и есть накладные расходы. Собственно, абзац после графиков отвечает на вопрос.

Это сколько?
Зависит от приложения. Для одних паузы в 100 мс критичны, другие и 5 секунд могут подождать.
Скажем так: если в 10 мс укладывается, значит, для большинства случаев сгодится.
Сам только недавно наткнулся, копаясь в исходниках Хотспота.
Есть планы опробовать на нашем Java сервере, где всё сетевое I/O на native методах.
Если есть только JavaCritical_myMethod, но нет Java_myMethod, бросится UnsatisfiedLinkError. Функция со стандартной сигнатурой нужна всегда. Для удобства она может просто распаковывать аргументы и передавать их уже в JavaCritical_ реализацию.
Не, этим только проверяется, что мы не пытаемся изменить состояние чужого потока.
Но любой поток может сам заходить в jni_critical (Thread::current() == this).

Информация

В рейтинге
Не участвует
Откуда
Санкт-Петербург, Санкт-Петербург и область, Россия
Работает в
Зарегистрирован
Активность