g.setStroke(new BasicStroke(params.legendDepth));
        g.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 20));
        int maxL = -1;
        List<String> representations = new ArrayList<String>();
        for (int i = 1; i <= functionConfigs.size(); i++) {
            String representation = String.format("f%d %-15s scale:[%d:%d]", i, functionConfigs.get(i - 1).getRepresentation(), functionConfigs.get(i - 1).getScaleX(), functionConfigs.get(i - 1).getScaleY());
            representations.add(representation);
            maxL = maxL < representation.length() ? representation.length() : maxL;
        }
        g.setColor(params.legendRectColor);
        g.drawRect(1, 1, maxL * 15, functionConfigs.size() * 20 + 5);
        g.setColor(params.legendBkColor);
        g.fillRect(2, 2, maxL * 15 - 1, functionConfigs.size() * 20 + 4);
        for (int i = 1; i <= functionConfigs.size(); i++) {
            g.setColor(params.legendFontColor);
            g.drawString(representations.get(i - 1), 5, i * 20);
            g.drawRect(maxL * 13, i * 20 - 11, 10, 10);
            FunctionConfig functionConfig = functionConfigs.get(i - 1);
            g.setColor(functionConfig.getGraphColor());
            g.fillRect(maxL * 13 + 1, i * 20 - 10, 9, 9);
            if (functionConfig.highlightHigher()) {
                g.setColor(params.legendFontColor);
                g.drawString(representations.get(i - 1), 5, i * 20);
                g.drawRect(maxL * 13 + 20, i * 20 - 11, 10, 10);
                g.setColor(functionConfig.heightLightHigherColor());
                g.fillRect(maxL * 13 + 21, i * 20 - 10, 9, 9);
            }
            if (functionConfig.highlightLower()) {
                g.setColor(params.legendFontColor);
                g.drawString(representations.get(i - 1), 5, i * 20);
                g.drawRect(maxL * 13 + 40, i * 20 - 11, 10, 10);
                g.setColor(functionConfig.heightLightLowerColor());
                g.fillRect(maxL * 13 + 41, i * 20 - 10, 9, 9);
            }
        }
}
  1. Краткая история WORA
  2. Виртуальные машины
    1. Регистровые машины

    2. Стековые машины

  3. Структура .class файла. часть I
  4. JVM часть I
  5. Структура .class файла. часть II
  6. JVM часть II
  7. Структура .class файла. часть III

  8. JVM часть III
  9. Оптимизации производимые javac
  10. Инструментарий

Agenda

Краткая история WORA

Виртуальные машины

Регистровые машины

R1: 

100

R2: 

135

R3: 

0

R1: 

100

R2: 

135

R3: 

ADD

ADD R1 R2 R3

0

235

Стековые машины

10
12
74
23

ADD

22
74
23

MUL

1628
23

POP

POP

_ADD

PUSH

POP

POP

_MUL

PUSH

Структура .class файла. часть I

Минорная и Мажорная версия

Размер пула констант

Все константы начинаются с тега

Пул констант

  • Размер пула всегда на один меньше
  • Все константы начинаются с тега
  • Очень много символьной информации(строки)
  • Большинство констант ссылаются на другие константы, почти все в итоге ссылаются на символьные
CONSTANT_NameAndType_info

name idx

descriptor idx

CONSTANT_Utf8_info

bytes

CONSTANT_Utf8_info

bytes

CONSTANT_Fieldref_info

class idx

name&type idx

CONSTANT_Class_info

name idx

CONSTANT_Utf8_info

bytes

Флаги доступа

Флаги доступа - маска флагов, используемых для обозначения прав доступа и свойств этого класса или интерфейса

Например: 0x4001 говорит, что перед нами public enum

0 1 1 1 0 1 1 0 0 0
1 1 0 0 0 1

public

final

super

interface

abstract

synthetic

annotation

enum

  • Класс - ссылка на структуру CONSTANT_Class_info
  • Супер класс - ссылка на структуру CONSTANT_Class_info
CONSTANT_Class_info

name idx

CONSTANT_Utf8_info

bytes

CONSTANT_Class_info

name idx

CONSTANT_Utf8_info

bytes

This class

Super class

This&Super&Interfaces

  • Список интерфейсов является набором ссылок на CONSTANT_Class_info в пуле констант

JVM часть I

INIT

Верификация

Подготовка

Разрешение

Boot Strap

Extension

Application

CLASSLOADER

Загрузка

Линковка

Предварительные шаги

Структура .class файла. часть II

Аттрибуты

Используются в ClassFile, field_info, method_info, и Code_attribute

name idx

bytes

Length

bytes

attribute_info 
CONSTANT_Utf8_info

Поля

name idx

bytes

field_info

access flag

descriptor idx

bytes

attributes

0 1 1 1 0 0 0 0 1 1
0 1 1 1 1 1

public

final

volatile

synthetic

enum

private

protected

static

transient

CONSTANT_Utf8_info
CONSTANT_Utf8_info
B byte
C char
D double
F float
I int
​J long
S short
Z boolean
L class
[ array

0x004A 0x0012 0x0018 0x0000

модификатор доступа, в данном случае

private static vilotile

атрибутов нет

0x0012
0x0A
0x0004
test

idx:

0x0018
0x0A
0x0001
B

idx:

Пример

Результат:

private static volatile byte test;

Методы

name idx

bytes

method_info

access flag

descriptor idx

bytes

attributes

CONSTANT_Utf8_info
CONSTANT_Utf8_info
0 0 0 1 1 1 0 1 1 1
1 1 1 1 1 1

public

final

synchronized

abstract

private

protected

static

native

bridge

vararg

strict

synthetic

0x000A 0x0012 0x0019 0x0001 0x0016 0x00000027 ...

модификатор доступа,

в данном случае

private static

один аттрибут, длинной 39 байт

0x0012
0x0A
0x0004
test

idx:

0x0019
0x0A
0x0028
(IDLjava/lang/Thread;)Ljava/lang/Object;

idx:

Пример

Результат:

private static Object test(int v1, double v2, Thread v3) { ... }

0x0016
0x0A
0x0004
Code

idx:

JVM часть II

Method area

Thread 1

Frame N

LVA

OS

FD

Frame 3

LVA

OS

FD

Frame 2

LVA

OS

FD

Frame 1

LVA

OS

FD

Thread stack

Thread 2

Frame N

LVA

OS

FD

Frame 3

LVA

OS

FD

Frame 2

LVA

OS

FD

Frame 1

LVA

OS

FD

Thread stack

Thread N

Frame N

LVA

OS

FD

Frame 3

LVA

OS

FD

Frame 2

LVA

OS

FD

Frame 1

LVA

OS

FD

Thread stack

pc reg 1

pc reg 2

pc reg N

HEAP

Native Method stack

Runtime

Структура .class файла. часть III

Атрибут "Code"

Состоит из:

  • максимальный размер для стека операндов(SO) и массива локальных переменных(LVA)
  • Собственно код
  • Таблица исключений
    • Указатель на начало блока try
    • Указатель на конец блока try
    • Указатель на начало catch блока
    • Указатель на класс ожидаемого эксепшена
  • Некий набор аттрибутов

Синтаксис Байт-кода

  • Большинство операций не требует аргументов
  • существует 5ть типа вызова метода:
    • invokedynamic - проверка типов происходит в рантайме
    • invokestatic - вызывает статический метод
    • invokevirtual - вызывает публичные(public) и защищенные(protected) не статические методы
    • invokeinterface - вызывает метод интерфейса
    • invokespecial - вызывает конструктор или приватные методы или методы родительского класса
  • Хорошо описаны в спецификации

Вызовы

    public void test() {
        // invokespecial #3                  
        // Method java/util/ArrayList."<init>":()V
        List<Integer> invokeinterface = new ArrayList<>();
        // invokeinterface #5,  2            
        // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        invokeinterface.add(1);
        ArrayList<Integer> invokevirtual = new ArrayList<>();
        // invokevirtual #6                  
        // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
        invokevirtual.add(1);
        // invokedynamic #7,  0              
        // InvokeDynamic #0:run:(Ljava/util/List;)Ljava/lang/Runnable;
        Runnable runnable = () -> invokeinterface.add(2);
        // invokestatic  #8                  
        // Method java/util/Collections.emptyList:()Ljava/util/List;
        List<Integer> invokestatic = Collections.emptyList();
    }
	public static int readIn(FileInputStream var$0, byte[] var$1) {
		//Max stack: 	5, Max locals: 	3, Code length: 	27b
		//Code:
		0:		getstatic Zax.done
		1:		aload_0
		2:		aload_1
		3:	 	iconst_0
		4:		aload_1

Пример

getstatic

LVA OS
idx val
0 var$0
1 var$1
LVA OS
idx val
0 var$0
1 var$1
Zax.done
	public static int readIn(FileInputStream var$0, byte[] var$1) {
		//Max stack: 	5, Max locals: 	3, Code length: 	27b
		//Code:
		0:		getstatic Zax.done
		1:		aload_0
		2:		aload_1
		3:	 	iconst_0
		4:		aload_1

aload_0

LVA OS
idx val
0 var$0
1 var$1
Zax.done
LVA OS
idx val
0 var$0
1 var$1
var$0
Zax.done
	public static int readIn(FileInputStream var$0, byte[] var$1) {
		//Max stack: 	5, Max locals: 	3, Code length: 	27b
		//Code:
		0:		getstatic Zax.done
		1:		aload_0
		2:		aload_1
		3:	 	iconst_0
		4:		aload_1

aload_1

LVA OS
idx val
0 var$0
1 var$1
var$0
Zax.done
LVA OS
idx val
0 var$0
1 var$1
var$1
var$0
Zax.done
	public static int readIn(FileInputStream var$0, byte[] var$1) {
		//Max stack: 	5, Max locals: 	3, Code length: 	27b
		//Code:
		0:		getstatic Zax.done
		1:		aload_0
		2:		aload_1
		3:	 	iconst_0
		4:		aload_1

iconst_0

LVA OS
idx val
0 var$0
1 var$1
0
var$1
var$0
Zax.done
LVA OS
idx val
0 var$0
1 var$1
var$1
var$0
Zax.done
	public static int readIn(FileInputStream var$0, byte[] var$1) {
		//Max stack: 	5, Max locals: 	3, Code length: 	27b
		//Code:
		0:		getstatic Zax.done
		1:		aload_0
		2:		aload_1
		3:	 	iconst_0
		4:		aload_1

aload_1

LVA OS
idx val
0 var$0
1 var$1
var$1
0
var$1
var$0
Zax.done
LVA OS
idx val
0 var$0
1 var$1
0
var$1
var$0
Zax.done
	public static int readIn(FileInputStream var$0, byte[] var$1) {
		//Max stack: 	5, Max locals: 	3, Code length: 	27b
		//Code:
		4:		aload_1
                5:		arraylength
		6:		invokevirtual FileInputStream.read([BII)I

arraylength

LVA OS
idx val
0 var$0
1 var$1
length
0
var$1
var$0
Zax.done
LVA OS
idx val
0 var$0
1 var$1
var$1
0
var$1
var$0
Zax.done
	public static int readIn(FileInputStream var$0, byte[] var$1) {
		//Max stack: 	5, Max locals: 	3, Code length: 	27b
		//Code:
		4:		aload_1
                5:		arraylength
		6:		invokevirtual FileInputStream.read([BII)I

invokevirtual

LVA OS
idx val
0 var$0
1 var$1
read
Zax.done
LVA OS
idx val
0 var$0
1 var$1
var$1
0
var$1
var$0
Zax.done
	public static int readIn(FileInputStream var$0, byte[] var$1) {
		//Max stack: 	5, Max locals: 	3, Code length: 	27b
		//Code:
		6:		invokevirtual FileInputStream.read([BII)I
		7:		iadd
		8:		dup

iadd

LVA OS
idx val
0 var$0
1 var$1
res
LVA OS
idx val
0 var$0
1 var$1
read
Zax.done
	public static int readIn(FileInputStream var$0, byte[] var$1) {
		//Max stack: 	5, Max locals: 	3, Code length: 	27b
		//Code:
		6:		invokevirtual FileInputStream.read([BII)I
		7:		iadd
		8:		dup

dub

LVA OS
idx val
0 var$0
1 var$1
res
res
LVA OS
idx val
0 var$0
1 var$1
res
	public static int readIn(FileInputStream var$0, byte[] var$1) {
		//Max stack: 	5, Max locals: 	3, Code length: 	27b
		//Code:
		8:		dup
		9:		putstatic Zax.done
		10:		ireturn

putstatic

LVA OS
idx val
0 var$0
1 var$1
res
LVA OS
idx val
0 var$0
1 var$1
res
res
	public static int readIn(FileInputStream var$0, byte[] var$1) {
		//Max stack: 	5, Max locals: 	3, Code length: 	27b
		//Code:
		8:		dup
		9:		putstatic Zax.done
		10:		ireturn

ireturn

LVA OS
idx val
0 var$0
1 var$1
LVA OS
idx val
0 var$0
1 var$1
res

Destroy

Frame

	public static int readIn(FileInputStream var$0, byte[] var$1) {
		//Max stack: 	5, Max locals: 	3, Code length: 	27b
		//Code:
		0:		getstatic Zax.done
		1:		aload_0
		2:		aload_1
		3:	 	iconst_0
		4:		aload_1
		5:		arraylength
		6:		invokevirtual FileInputStream.read([BII)I
		7:		iadd
		8:		dup
		9:		putstatic Zax.done
		10:		ireturn
		11:		astore_2
		12:		new
		13:		dup
		14:		aload_2
		15:		invokespecial RuntimeException.<init>(Ljava/lang/Throwable;)V
		16:		athrow
	}
    public static int readIn(FileInputStream fis, byte[] arr) {
        try {
            return done += fis.read(arr, 0, arr.length);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

Байт-код

Java-код

  public static int readIn(java.io.FileInputStream, byte[]);
    Code:
       0: getstatic     #12 // Field done:I
       3: aload_0
       4: aload_1
       5: iconst_0
       6: aload_1
       7: arraylength
       8: invokevirtual #11 // Method java/io/FileInputStream.read:([BII)I
      11: iadd
      12: dup
      13: putstatic     #12 // Field done:I
      16: ireturn
      17: astore_2
      18: new           #36 // class java/lang/RuntimeException
      21: dup
      22: aload_2
      23: invokespecial #37 // Method java/lang/RuntimeException."<init>":(Ljava/lang/Throwable;)V
      26: athrow

Таблица исключений

start pc end pc handler pc catch type
0 16 17 Class java/io/IOException

JVM часть III

Генератор промежуточного кода

Оптимизатор

Генератор нативного кода

Профайлер

Интерпретатор

JNI

Исполнение

JIT

Оптимизации производимые javac

Почти никаких - все на откуп JIT

Флаг -o игнорируется с версии java 1.3

Инструменты

Генерация кода

Декомпиляция

Q/A

Java Once; Java Anywhere

By Roman Makhlin

Java Once; Java Anywhere

  • 514