- В числовых литералах группы цифр теперь можно разделить подчеркиванием:
public final static int INT_WITH_UNDERSCORES = 100_000; - Добавлены бинарные литералы с префиксом 0b:
public final static int BINARY_INT = 0b001100; - В качестве ключа switch теперь можно применять тип String:
switch("one") {
case "one" :
case "two" : System.out.println("JSR 334");
} - Теперь можно не повторять определение типа при создании объекта generic класса:
List<String> foo = new ArrayList<>(); - В блоке catch можно перечислить несколько классов исключений:
try {
throw new NullPointerException();
} catch (ArithmeticException | NullPointerException e) {
} - UPD Для целей проверки синтаксиса используется наименьший общий тип перечисленных исключений:
try {
throw new NullPointerException();
} catch (NullPointerException | ArithmeticException e) {
// Будет ошибка компиляции
// ArithmeticException a = e;
// Общий тип
RuntimeException r = e;
} - Добавлены автоматически закрывающиеся после выполнения блока try ресурсы, которые должны реализовывать интерфейс java.lang.AutoCloseable:
class Resource implements AutoCloseable {
@Override
public void close() throws Exception {}
} - Конструкция try с автоматически закрывающимся ресурсом может быть без catch и finally:
try (Resource resource = new Resource()) {
throw new Exception();
} - В методах и конструкторах, использующих переменное число аргументов переменного типа теперь будет выдаваться предупреждение unchecked or unsafe operation, если они не аннотированы SafeVarargs. Аннотировать можно конструкторы, final и static методы:
class Coin<T> {
@SafeVarargs
public Coin(T ... args){
}
@SafeVarargs
public final void instanceMethod(T ... args){
}
@SafeVarargs
public static void staticMethod(K ... args){
}
}
Что видит DPI, и что мы попробовали у него отобрать
Последние пару лет я работаю в команде, которая занимается устойчивой к DPI (Deep Packet Inspection) туннельной инфраструктурой — по сути, альтернативой классическому VPN.
Когда начинаешь заниматься этим всерьёз, довольно быстро обнаруживается неприятная вещь: шифрование само по себе давно уже не означает, что трафик нельзя распознать. Содержимое пакетов действительно можно скрыть, но пакет от этого не исчезает. У него остаются размер, направление, время появления; соединение начинается с определённой последовательности сообщений, TLS-клиент определённым образом представляется серверу, поток ускоряется, замедляется, замирает и снова начинает передавать данные.
Для человека всё это выглядит как куча зашифрованных байтов. Для классификатора — как вполне пригодный набор признаков.
Поэтому значительная часть нашей работы в итоге свелась не к тому, чтобы «зашифровать ещё сильнее», а к более практическому вопросу: что именно видит наблюдатель снаружи и по каким признакам он может решить, что перед ним не браузерный трафик, а туннель.
Об этом и расскажу.

