int i = 2;
if (i = 4) {
printf("head\n");
} else {
printf("tail\n");
}@inponomarev
Ivan Ponomarev, Synthesized.io/MIPT
![]() |
|
![]() | ![]() | ![]() |
Cay S. Horstmann. Core Java vol 1 & 2
Raoul-Gabriel Urma et al. Modern Java in Action
![]() | ![]() |
Joshua Bloch Effective Java
Brian Goetz et al. Java Concurrency in Practice
Устаревший язык, на нём, наверное, уже новых проектов и не пишет никто…
Языки вообще учить не надо: Claude всё напишет за нас…
Что такого я узнаю на лекциях, чего нет онлайн?..
— всё это правильные вопросы! Отвечу на них с конца…
Инженерия — искусство компромиссов (engineering trade-offs).
Осваивать это искусство хорошо на удачных примерах из прошлого.
Java — такой пример.
Инженеру в наше время не так важно знать конкретный язык, как понимать, что компромисс неизбежен, и уметь выбирать наилучший.
Язык + виртуальная машина: https://docs.oracle.com/javase/specs/index.html
Java Language Specification (872 стр)
Java Virtual Machine Specification (626 стр)
Экосистема
стандартная библиотека,
иные JVM-языки (Kotlin, Scala, Groovy), и реализации языков для JVM (JRuby)
Репозиторий библиотек Maven Central и огромное количество переиспользуемого кода
Тулинг (IDE, инструменты тестирования)
![]() James Gosling (JPoint 2020) |
|
The Java Story: The Official Documentary, July 2026
https://www.youtube.com/watch?v=ZqGSg4b_cZA
Q&A with James Gosling, June 2020:
https://www.youtube.com/watch?v=XThhlihqTXI
| ![]() |
Повсюду: от чипов в банковских картах до серверов в дата-центрах.
![]() |
| ![]() |
![]() |
При разработке Android, Google использовали Java как язык, javac, стандартные API, байткод, но не виртуальную машину и не реализацию API.
11 лет судов Google с Oracle (2010—2021), пока решение не было вынесено в пользу Google.
Kotlin (язык, компилирующийся в тот же JVM байт-код) провозглашён основным языком Android.
Oracle не признаёт настоящей «Джавой» то, что работает на Android.
По некоторым оценкам, в мире около 3.9 млрд Android-устройств.
Напечатает | Не скомпилируется (как и в C, |
Язык допускает подобный код (компилятор, в зависимости от версии и настроек, может выдать warning). | Не скомпилируется (unreachable statement не допустим). |

Неопределённое поведение | 3 + 4 + 5 = 12 |
Неопределенное поведение (включая чтение чужих данных или segmentation fault). |
|
Неопределенное поведение (включая аварийное завершение программы). |
|
На разных типах компьютеров разные
Endianness…
Размер регистров и ссылок (sizeof(int), sizeof(void *)…
Floating point hardware & format…
Приходилось разрабатывать разные версии программ для разных платформ (или писать спагетти из #ifdef)
Java bytecode — исполняемый код виртуальной машины. Виртуальные машины (написанные на C++) написаны для разных платформ, все они исполняют байт-код.
LLVM intermediate representation — схожая идея, появившаяся позднее.
Решается вопрос не только кроссплатформенности, но и безопасности.
![]() | ![]() |

Перед выполнением байткода, JVM выполняет его статическую проверку (https://docs.oracle.com/javase/specs/jvms/se25/html/jvms-4.html#jvms-4.10)
Если код невалидный (например, stack underflow) — VerifyError

JVM начинает исполнение с интерпретации байт-кода, накапливая статистику выполнения.

По мере того, как накапливается статистика использования кода, код компилируется в оптимизированный машинный код с использованием допущений, накопленных по статистике выполнения.
Скомпилированный код хранится в Code Cache (специальном сегменте оперативной памяти).

Если путь выполнения меняется, срабатывает "uncommon trap" и выполнение возвращается к интерпретатору.
| ![]() |
| ![]() |
| ![]() |
| ![]() |
| ![]() |
Нет больше * и &, всё определено за нас.
«Объекты» и «примитивы/value-объекты» ведут себя по-разному.
| ![]() |
| ![]() |
| ![]() |
| ⇒ нет проблемы «висячих» ссылок |
| ⇒ нет проблемы «потерянных» ссылок |
| Компромисс ради быстродействия при отсутствии лучшего решения. Осложнил систему типов, обучение языку Java, привёл к дальнейшим проблемам типа использования типов-обёрток в generics. |
C#: «соперник Java», на 4 года моложе Джавы
|
Rust: «соперник C», примерно на 10 лет моложе Джавы
|
Потребляет слишком много памяти
Медленно стартует
Многословна (слишком много "boilerplate code")
Язык консервативен, медленно развивается (этот аргумент, в частности, привёл к появлению новых JVM языков: Scala, Groovy, Xtend, Kotlin).
С 2018 года Oracle перешёл на 6-месячный цикл релизов.

https://redmonk.com/ — Альтернатива TIOBE с 2012 г., GitHub+StackOverflow. Проблема: StackOverflow, достигавший пика в 2016м, теперь практически мёртв.
Мир меняется, языки и платформы развиваются в условиях жёсткой конкуренции — Java не исключение.
Как ни измеряй, Java/JVM на протяжении 30 лет была и продолжает быть одной из ведущих экосистем.
Garbage Collection
MultiThreading & Memory Model
Загрузка и исполнение кода в runtime
Рефлексия
Стандартная библиотека
Достоинства
WORA
Safety/техническая безопасность: исключение фатальных сбоев на сервере
Security/информационная безопасность: защита от злонамеренных действия
Недостатки
Overhead по производительности и памяти
Отсутствие гибкости, предоставляемой низкоуровневыми языками
The developer does not need to worry about freeing up memory
Garbage collection when there are no references to the object
Advantages:
Less code
There are no invalid links (to destroyed objects)
Fewer memory leaks
Disadvantages:
We do not control the operating time of the GC
STW-pauses (sometimes at the inappropriate time)
GC полностью изолирован от исполняемого кода.
Семантика не меняется при замене одного GC на другой!
![]() |
| ![]() |
Latency | ![]() | Throughput |
Многопоточность
Возможность запуска параллельных потоков выполнения встроена в язык с первой версии (Thread, Runnable etc)
Memory Model
Часть спецификации VM: модель того, как работает хранилище данных в условиях многопоточного доступа
Отвечает на вопрос: «какие значения может прочитать конкретный read в программе?»
class DumbWayToFallAsleep implements Runnable {
private boolean asleep;
public void setAsleep(boolean asleep){
this.asleep = asleep;
}
@Override
public void run() {
while (!asleep){
//countSomeSheep
//WILL WE FALL ASLEEP?
}
}
}class NotSoDumbWayToFallAsleep implements Runnable {
private volatile boolean asleep;
public void setAsleep(boolean asleep){
this.asleep = asleep;
}
@Override
public void run() {
while (!asleep){
//countSomeSheep
//...
}
}
}Compiled class bytecode can be delivered to any system in the runtime (most often by saving a file to the file system).
Recompilation/linking is not required.
An idea that seemed very good at first!
Исследование информации о классах, полях, методах и т. д. во время выполнения
Чтение/модификация полей (в том числе private!) и динамический вызов методов (в том числе private!)
Proxy and AOP
System-independent part
Data structures
Mathematics
System-dependent part
Date and time
File system access
Network access
User Interface
Any .jar file compiled many years ago can be run on any modern JVM
A gift or a curse?
type inference (var),
switch expressions,
text blocks
sealed classes,
pattern matching (instanceof, switch),
records,
unnamed main classes,
virtual threads…
Project Amber: productivity-oriented features (например: flexible constructors)
Project Loom: fibers & continuators
Project Valhalla: value objects
Panama: Java & native code connection
Leyden: improve startup time
etc…
There is a virtual machine: you can compile to the byte code from any language!
20-30 languages
Специально созданные: Groovy, Scala, Kotlin, Xtend…
Реимплементация для JVM: JRuby, Clojure (Lisp dialect), Nashorn/Graal.js…
Библиотеки и фреймворки (в т. ч. для тестирования)
Среды разработки
Репозиторий Maven Central
Системы сборки
IDEA (proprietary, JetBrains) | NetBeans (ASF / Oracle) |
Eclipse Foundation |
VS Code (Microsoft) |
22 миллиона пакетов, 2-3 млн новых пакетов каждый год (https://mvnrepository.com/repos/central)
Условие публикации — open source (хотя есть исключения), обязательно прикладывать исходники и электронную подпись.
В отличие от PyPI и npm, авторы имеют group id, основанный на домене организации (com.microsoft, org.atp-fivt), и производится процесс верификации домена.
XML configuration | ![]() Groovy DSL / Kotlin DSL |
Conferences (Joker/JPoint/SnowOne, DevoXX etc.)
JUGs
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>hello-world</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.release>25</maven.compiler.release>
</properties>
</project>src/main/java/org/example/Main.java
package org.example;
public class Main {
static void main() {
IO.println("Hello World!");
}
}mvn package
java -cp target/hello-world-1.0-SNAPSHOT.jar org.example.Main