@hirthwork

Тег java в блоге hirthwork

hirthwork

Решил Х-ворк поддержку IDN в java.net.URI добавить.
Итого найдено две баги в java.net.URI и не понятно вообще как этим говном пользоваться можно.

hirthwork

Есть такой класс в Java NIO: java.net.SocketChannel
Для удобства олдфагов у него есть метод Socket socket();
Соответственно олдфаги могут делать channel.socket().getInputStream() и channel.socket().getOutputStream() и пердолиться в массивчики вместо того, чтобы читать документацию по непонятному ByteBuffer.
Недоверчивые олдфаги естественно сначала написали тест где сделали channel.socket().getInputStream().read() и убедились, что он кидает эксепшен по таймауту.
Ваш покорный слуга и слишком доверчивый олдфаг сегодня в продакшене узнал, что channel.socket().getOutputStream().write(buf) таймаута по эксепшену не кидает.
Не используйте Джаву. Оставьте это мне. Через страдания я приду к искуплению.

hirthwork


Took me a while

hirthwork

Использовали долгие годы IBM JRE
@
Хуяк, баг в продакшене. Два дня охотились, обложили всё логами, пришли к выводу, что бага в JIT
@
А чего бы не попробовать OpenJDK, вон там даже Shenandoah GC впилили
@
В OpenJDK в JIT нашлась другая бага
@
Смогли составить минимальный тест-кейз, зарепортили
@
В OpenJDK багу починили
@
Пробуем OpenJDK, заебца работает на том проекте, где была бага в IBM JRE

... meanwhile at another project

А попробую ка я впилить BouncyCastle в качестве TLS provider.
@
Хм... никаких улучшений по скорости. Попробую ка туда OpenJDK с Shenandoah GC воткнуть
@
Ну да, стало сильно лучше. Попробую ка дефолтный TLS provider использовать
@
ЕЩЁ ОДНА БАГА В JIT

Мораль: не бывает тривиальных изменений. Если две реализации не противоречат спецификации, то это вовсе не значит, что они не противоречат друг другу.

hirthwork

Что будет если запихнуть 6 миллионов IPv4 значений в HashSet? Большинство скажут, что будет бо-бо, потому что у хэшсета на каждую ноду оверхед в 48 байт на 64-битной машине.
Более опытные разработчики скажут, что оверхед всего 24 байта, потому что java по дефолту использует -XX:UseCompressedOops (a.k.a. -Xcompressedrefs) и при размере памяти меньше 32 ГБ на каждый указатель тратится всего 4 байта.

hirthwork

Здравствуйте, мои маленькие любители поебатися с байткодом. Сегодня я вам расскажу о crucial difference различных access specifiers при объявлении мемберов inner-классов.
Слово в сторону: любой порядочный параноик объявит мембер своего класса как private, а не как либо ещё. Крайне ленивый раздолбай вообще access specifier не напишет. И вот тут-то и зарыта собака.
Возьмём вот такой класс с двумя inner-классами:

public class Main {
    class Inner {
        int field;
    }

    class Pinner {
        private int field;
    }

    int test(final Inner obj) {
        return obj.field;
    }

    int test(final Pinner obj) {
        return obj.field;
    }
}

Ничег сложного, просто два inner-класса, у одного поле int, у другого — private int. Ну и из двух разных функций обращаемся к этим полям.
Скомпилим и посмотрим на байткод:

$ javac Main.java
$ javap -p -c Main.class
Compiled from "Main.java"
public class Main {
  public Main();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  int test(Main$Inner);
    Code:
       0: aload_1
       1: getfield      #2                  // Field Main$Inner.field:I
       4: ireturn

  int test(Main$Pinner);
    Code:
       0: aload_1
       1: invokestatic  #3                  // Method Main$Pinner.access$000:(LMain$Pinner;)I
       4: ireturn
}

Ну ничего себе! Было private int простое, а стало золотое — вместо банального getfield получаем invokestatic, который...

$ javap -p -c Main\$Pinner.class
Compiled from "Main.java"
class Main$Pinner {
  private int field;

  final Main this$0;

  Main$Pinner(Main);
    Code:
       0: aload_0
       1: aload_1
       2: putfield      #2                  // Field this$0:LMain;
       5: aload_0
       6: invokespecial #3                  // Method java/lang/Object."<init>":()V
       9: return

  static int access$000(Main$Pinner);
    Code:
       0: aload_0
       1: getfield      #1                  // Field field:I
       4: ireturn
}

... внутри уже сам делает getfield, т.е. на ровном месте получили лишний вызов функции. А ещё когда вы сделаете что-то вроде:

Pinner pinner = null;
return pinner.field;

То в стектрейсе NullPointerException вы получите лишний фрейм с этим самым Main$Pinner.access$000, который неопытного программиста просто вводит в ступор.

В общем, я сейчас борюсь с желанием повсюду в коде поудалять все private.

hirthwork

tfw проклятые капиталисты берут на поддержку богохранимую java8 и обещают раздавать секурити апдейты аж до 2023 года без регистрации и смс: http://www.opennet.ru/opennews/art.shtml?num=49623

hirthwork

После двух часов попыток починить то что не ломал, ничто так не греет душу, как аккуратный NullPointerException

hirthwork

Уж если включил -Xverbosegclog, то будь добр, пиши его в /dev/shm/

hirthwork

Здравствуй, дорогой дневничок. Я заебался. Я себе сломал мозг об java.nio.ByteBuffer.
Чтобы не ломать каждый раз, сделал себе удобную пикчу, чтобы сразу было видно, что делает каждая операция.
Попробуйте и вы: https://tinystash.undef.im/...JZCFRvasdjVH7ze5.svg

hirthwork

Словил StackOverflowError от javac

hirthwork

В регулярках джавы можно сделать named capturing groups (если вы не знаете что это такое, то вам не сюда, а в кружок кройки и шитья), и по имени группы из Matcher'а можно доставать captured подстроку. Но при этом из скомпиленной регулярки нельзя достать список имён этих самых capturing groups, которые были заданы в регулярке. Второтег

hirthwork

Иногда ты используешь type erasure, а иногда type erasure имеет тебя

hirthwork

Забавная история. Привык что в джаве статическая инициализация класса происходит в первую очередь при его загрузке. Однако не всё так просто — до статической инициализации происходит инициализация полей enum'а:

enum MyEnum {
    INSTANCE;

    static {
        System.out.println("static");
    }

    MyEnum() {
        System.out.println("c'tor");
    }
}

public class Main {
    public static void main(final String[] args) {
        System.out.println("main");
        System.out.println(MyEnum.INSTANCE);
    }
}

Печатает:

main
c'tor
static
INSTANCE
hirthwork

Переизобрёл unified diff. Просто потому что могу.

hirthwork

Ну пиздец, теперь весь код с синхронайзедов на локи переписывать: https://www.ibm.com/develop...-jtp10264/index.html

hirthwork

минутка рекламы: http://www.twmacinta.com/myjava/fast_md5.php — охуенная реализация, которая работает в два раза быстрее родной реализации MD5 в джаве // завтра катну в продакшен и посмотрю что распидорасит

hirthwork
Map<String, Integer> m = ...;
Number n = m.getOrDefault(key, new Double(0.5d));

Не компилится. А всё потому, что авторам лень было сделать эту функцию дженериком. Говно, кароч
// Плюсопетухи приглашаются покукарекать о том что это ненужно, потому что у них такого нет

hirthwork

Не используйте FilterOutputStream — это говно: http://grepcode.com/file/re...utputStream.java#120

hirthwork

знатно объебался со своим повсеместным использованием try-with-resources
уж если возможна в логике ситуация, когда close вызывать не нужно, то и нехуй try-with-resources тогда в этом месте использовать

Добавить пост

Вы можете выбрать до 10 файлов общим размером не более 10 МБ.
Для форматирования текста используется Markdown.