java 11

background image

Programowane dynamiczne

1

1. Ładowanie klas

2. Specyfikacja pliku

class

analiza przykładu: Hello world!

narzędzie ASM

3. Programowanie aspektowe

AspectJ

background image

Klasa abstrakcyjna ClassLoader

2

Do pobrania klasy JVM wykorzystuje instancję klasy

java.lang.ClassLoader

.

Każda klasa zawiera referencję do do ładującego ją obiektu. Programista może

sterować procesem ładowania klas:

ClassLoader

loader

=

new

NetworkClassLoader(

host

,

port

);

Object main = loader.loadClass(

"Main"

,

true

).newInstance();

. . .

Przykładowa klasa:

class

NetworkClassLoader

extends

ClassLoader {

String

host

;

int

port

;

public

Class findClass(String name) {

byte

[] b = loadClassData(name);

return

defineClass(name, b, 0, b.

length

);

}

private

byte

[] loadClassData(String name) {

// load the class data from the connection

}

}

background image

Plik class

3

public

class

Main {

/**

*

@param

args

*/

public

static

void

main(String[] args){

System.

out

.println(

"Hello world!"

);

}

}

Nagłówek klasy:

CA FE BA BE

– identyfikator formatu pliku class.

00 00

00 2E

– numer wersji JVM: (

46

.

0

) – zgodność z Java 1.2

Ogólnie JVM 1.k (k>1) obsługuje klasy od 45.0 do 44+k.0 włącznie

00 22

– ilość deklarowanych elementów (Constant Pool). Po tej deklaracji

następują kolejne, 33 elementy.

background image

Plik class - Constant Pool

4

1.

01

00 04

4D 61 69 6E

string kodowany w UTF-8

o długości

4

:

Main

2.

07

00 01

pierwszy

z elementów to

nazwa klasy

3.

01

00 10

java/lang/Object

4.

07

00 03

trzeci

element to

nazwa klasy

5.

01

00 06

<init>

6.

01

00 03

()V

7.

01

00 04

Code

8.

0C

00 05 00 06

– piąty

element to

nazwa metody lub atrybutu

,

szósty

to

typ

(sygnatura)

: brak argumentów:

()

, zwracany typ

void

:

V

9.

0A

00 04 00 08

klasa

(

czwarty element

)

zawiera metodę

(

ósmy element

)

10.

01

00 0F

LineNumberTable

11.

01

00 12

LocalVariableTable

background image

Plik class - Constant Pool

5

12.

01

00 04

this

13.

01

00 06

LMain;

14.

01

00 04

main

15.

01

00 16

([Ljava/lang/String;)V

16.

01

00 10

java/lang/System

17.

07

00 10

szesnasty

element to

nazwa klasy

18.

01

00 03

out

19.

01

00 15

Ljava/io/PrintStream;

20.

0C

00 12 00 13

– 18-ty

element to

nazwa metody/atrybutu

,

19-ty

to

jego typ

21.

09

00 11 00 14

– 17-ta

klasa zawiera

20-ty

atrybut

22.

01

00 0C

Hello world!

23.

08

00 16

– 22-gi

element to

stała tekstowa

24.

01

00 13

java/io/PrintStream

25.

07

00 18

– 24-ty

element to

nazwa klasy

background image

Plik class - Constant Pool

6

26.

01

00 07

println

27.

01

00 15

(Ljava/lang/String;)V

28.

0C

00 1A 00 1B

– 26-ty

element to

nazwa metody/atrybutu

,

27-ty

to

jej

sygnatura

29.

0A

00 19 00 1C

– 25-ta

klasa zawiera

28-tą

metodę

30.

01

00 04

args

31.

01

00 13

[Ljava/lang/String;

32.

01

00 0A

SourceFile

33.

01

00 09

Main.java

background image

Plik class

7

00 21

– modyfikatory dostępu dla klasy:

ACC_PUBLIC

(

00 01

)

|

ACC_SUPER

(

00

20

) – ze względu na kompatybilność ze starszymi JVM.

00 02

– numer elementu określającego klasę definiowaną w tym pliku.

00 04

– numer elementu określającego nadklasę klasy definiowanej w tym pliku.

00 00

– liczba interfejsów

00 00

– liczba atrybutów

00 02

– liczba metod

background image

Plik class – metoda <init>

8

00 01

ACC_PUBLIC

– metoda publiczna

00 05

– indeks elementu zawierającego nazwę metody:

<init>

00 06

– indeks elementu z sygnaturą metody:

()V

00 01

– liczba dodatkowych atrybutów metody

00 07

– indeks elementu z nazwą atrybutu:

Code

00 00 00 2F

– długość atrybutu

00 01

– rozmiar stosu

00 01

- rozmiar tablicy zmiennych lokalnych

00 00 00 05

– długość kodu

2A B7 00 09 B1

00 00

– długość tablicy wyjątków

00 02

– liczba dodatkowych atrybutów

background image

Plik class – metoda <init>

9

00 0A

LineNumberTable

00 00 00 06

– długość atrybutu

00 01

– długość tabeli numerów linii

00 00

– indeks instrukcji w tabeli

Code

00 06

– odpowiadający jej numer linii w pliku źródłowym

00 0B

LocalVariableTable

00 00 00 0C

– długość atrybutu

00 01

– długość tabeli zmiennych lokalnych

00 00

– początek zmiennej lokalnej w tablicy zmiennych

00 05

– długość zmiennej

00 0C

– indeks zmiennej:

this

00 0D

– typ zmiennej:

LMain

00 00

– indeks w lokalnej tablicy zmiennych

background image

Plik class – metoda <init>

10

Kod metody

<init>

:

2A B7 00 09 B1

2A

:

ALOAD_0

//

zmienna lokalna o adresie 0 jest wstawiana na stos

B7

00 09

:

INVOKESPECIAL

java/lang/Object.<init>()V;

//

wywołuje metodę

void Object.<init>();

B1

:

RETURN

//

zwraca typ

void

background image

Plik class – metoda main

11

00 09

ACC_PUBLIC

(

00 01

)

|

ACC_STATIC

(

00 08

) – publiczna metoda

statyczna

00 0E

– indeks elementu zawierającego nazwę metody:

main

00 0F

– indeks elementu z sygnaturą metody:

([Ljava/lang/String;)V

00 01

– liczba dodatkowych atrybutów metody

00 07

– indeks elementu z nazwą atrybutu:

Code

00 00 00 37

– długość atrybutu

00 02

– rozmiar stosu

00 01

- rozmiar tablicy zmiennych lokalnych

00 00 00 09

– długość kodu

B2 00 15 12 17 B6 00 1D B1

00 00

– długość tablicy wyjątków

00 02

– liczba dodatkowych atrybutów

background image

Plik class – metoda main

12

00 0A

LineNumberTable

00 00 00 0A

– długość atrybutu

00 02

– długość tabeli numerów linii

00 00

– indeks instrukcji w tabeli

Code

00 0C

– odpowiadający jej numer linii w pliku źródłowym

00 08 00 0D

to samo dla kolejnej linii

00 0B

LocalVariableTable

00 00 00 0C

– długość atrybutu

00 01

– długość tabeli zmiennych lokalnych

00 00

– początek zmiennej lokalnej w tablicy zmiennych

00 09

– długość zmiennej

00 1E

– indeks zmiennej:

Hello world!

00 1F

– typ zmiennej: stała tekstowa

00 00

– indeks w lokalnej tablicy zmiennych

background image

Plik class – metoda main

13

Kod metody

main

:

B2 00 15 12 17 B6 00 1D B1

B2

00 15

:

GETSTATIC

java/lang/System.out :

Ljava/io/PrintStream;

//

inicjalizacja klasy/obiektu

System.out

i odłożenie

//

go na stos

12

17

:

LDC

Hello world!

//

załadowanie na stos stałej tekstowej

B6

00 1D

:

INVOKEVIRTUAL

java/io/PrintStream.println(Ljava/lang/String;)V

//

wywołuje metodę

System.out.println(String)

B1

:

RETURN

//

zwraca typ

void

background image

Plik class

14

00 01

– liczba atrybutów

00 20

SourceFile

00 00 00 02

– długość atrybutu

00 21

Main.java

KONIEC!!!

background image

Plik class – zapis assemblerowy

15

// class version 46.0 (46)
// access flags 33
public class Main {
// compiled from: Main.java

// access flags 1
public <init>()V
L0 (0)
LINENUMBER 6 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init>()V
RETURN
L1 (4)
LOCALVARIABLE this LMain; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1

// access flags 9
public static main([Ljava/lang/String;)V
L0 (0)
LINENUMBER 12 L0
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "Hello world!"
INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
L1 (4)
LINENUMBER 13 L1
RETURN
L2 (6)
LOCALVARIABLE args [Ljava/lang/String; L0 L2 0
MAXSTACK = 2
MAXLOCALS = 1
}

background image

ASM

16

ASM (http://asm.objectweb.org/index.html) jest narzędziem służącym do operacji na

plikach binarnych Javy. Może być używany do dynamicznego generowania klas lub

interfejsów bezpośrednio w formie binarnej lub modyfikacji istniejących klas

w trakcie ich ładowania przez Wirtualną Maszynę Javy.

Inne narzędzia tego typu:

BCEL: http://jakarta.apache.org/bcel/

SERP: http://serp.sourceforge.net/

Javassist: http://www.csg.is.titech.ac.jp/~chiba/javassist/

background image

ASM

17

Przykład – program generujący klasę z dzisiejszego wykładu (Hello world!):

import org.objectweb.asm.ClassWriter;

import org.objectweb.asm.MethodVisitor;

import org.objectweb.asm.Opcodes;

import org.objectweb.asm.Type;

import org.objectweb.asm.commons.GeneratorAdapter;

import org.objectweb.asm.commons.Method;

import java.io.FileOutputStream;

import java.io.PrintStream;

public class Helloworld extends ClassLoader implements Opcodes {

public static void main(final String args[]) throws Exception {

ClassWriter cw = new ClassWriter(false);

cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);

background image

ASM

18

// metoda init

MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null,

null);

mw.visitVarInsn(ALOAD, 0);

mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", ()V");

mw.visitInsn(RETURN);

mw.visitMaxs(1, 1); // glebokość stosu i liczba zmiennych lokalnych

mw.visitEnd();

// metoda main

mw = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main",

"([Ljava/lang/String;)V", null, null);

mw.visitFieldInsn(GETSTATIC, "java/lang/System", "out",

"Ljava/io/PrintStream;");

mw.visitLdcInsn("Hello world!");

mw.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",

"(Ljava/lang/String;)V");

mw.visitInsn(RETURN);

background image

ASM

19

mw.visitMaxs(2, 2);

mw.visitEnd();

byte[] code = cw.toByteArray(); // pobieramy kod klasy

FileOutputStream fos = new FileOutputStream("Example.class");

fos.write(code);

fos.close();

Helloworld loader = new Helloworld();

Class exampleClass = loader.defineClass("Example",code,0,code.length);

exampleClass.getMethods()[0].invoke(null, new Object[] { null });

background image

ASM

20

// inny sposob uzyskania tego samego efektu

cw = new ClassWriter(true);

cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);

Method m = Method.getMethod("void <init> ()");

GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null,

cw);

mg.loadThis();

mg.invokeConstructor(Type.getType(Object.class), m);

mg.returnValue();

mg.endMethod();

m = Method.getMethod("void main (String[])");

mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw);

mg.getStatic(Type.getType(System.class), "out",

Type.getType(PrintStream.class));

background image

ASM

21

mg.push("Hello world!");

mg.invokeVirtual(Type.getType(PrintStream.class),

Method.getMethod("void println (String)"));

mg.returnValue();

mg.endMethod();

cw.visitEnd();

code = cw.toByteArray();

loader = new Helloworld();

exampleClass = loader.defineClass("Example", code, 0, code.length);

exampleClass.getMethods()[0].invoke(null, new Object[] { null });

}

}

background image

Programowanie aspektowe

22

Każde realizowane zagadnienie pociąga za sobą w praktyce potrzebę realizacji

zagadnień pobocznych. Najczęściej spotykane zagadnienia są związane

z logowaniem, bezpieczeństwem, spójnością transakcyjną, autoryzacją,

synchronizacją wielowątkową itd. Jest to zjawisko normalne, wynikające ze

złożoności wymagań klienta. Zagadnienia te są w dużym stopniu rozłączne

pomiędzy sobą pod względem funkcjonalnym. Aby je zrealizować programista musi

poprzeplatać ich implementacje (tzw. warkocz), co czyni kod mniej czytelnym,

bardziej podatnym na błędy, trudniejszym w modyfikacji.

Programowanie aspektowe (Aspect Oriented Programming) zapobiega tym

negatywnym skutkom oddzielając fizycznie kod każdego zagadnienia poprzez

umieszczenie go w oddzielnych aspektach wraz z określniem punktów interakcji

pomiędzy nim a kodem programu.

Źródło: http://pl.wikipedia.org/wiki/Programowanie_aspektowe

background image

AspectJ

23

AspectJ to aspektowy język programowania opracowany w Xerox Palo Alto

Research Center. Kluczowe cechy języka:

AspectJ jest rozszerzeniem języka Java. Kompilator (ajc) tworzy kod źródłowy

w Javie kompilowany dalej do postaci binarnej (pliki class).

aspekty implementowane przez AspectJ są obiektami

obsługuje wszystkie techniki programowania aspektowego, w tym: punkty

złączenia, punkty przekroju, rady, mechanizmy zarządzające cyklem życia aspektu

Obecnie AspectJ jest rozwijany w ramach projektu Eclipse:

http://www.eclipse.org/aspectj/. Istnieją również narzędzia developerskie (AJDT).

background image

Model punktów złączenia

24

Każdy język programowania określa zbiór potencjalnych punktów złączenia – model

punktów złączenia. Przykładowe potencjalne punkty złączenia w Javie to:

wywołanie metody,

wykonanie metody,

wejście do statycznego bloku kodu,

wywołanie konstruktora.

Punkty złączenia są miejscami w które można wstawić tzw. logikę przekrojową. Po

wstawieniu dodatkowej logiki (kodu programu) w punkt złączenia staje się on

punktem przekroju

background image

Punkty przekroju

25

Deklaracja punktów złączenia:

public pointcut myClassTaskCalled() :

call(public void MyClass.task());

Punkt złączenia dla wszystkich metod

task()

niezależnie od klasy:

public pointcut anyClassTaskCalled() : call(* *.task(..));

Przekazanie wartości do punktu złączenia:

public pointcut anyClassTaskCalled(int value) :

call(* *.task(..)) && args(number);

Typy punktów złączenia:

call (Signature)

– wywołanie metody

execution (Signature)

– wykonanie metody

handler(TypePattern)

– przechwytywanie wyjątków

background image

Rady

26

Rada (advice) określa kod wykonywany w momencie zarejestrowania punktu

złączenia. Od zwykłej metody różni ją dodatkowe słowo kluczowe określające

miejsce wykonania kodu względem punktu złączenia:

before()

– przed punktem złączenia,

around()

– zamiast punktu złączenia, chyba że metoda

proceed()

mówi inaczej

after()

– po punkcie złączenia niezależnie od wyniku jego działania

after() returning

– po punkcie zgłoszenia jeśli nie było zgłoszenia wyjątku

after() throwing

– po punkcie zgłoszenia jeśli został zgłoszony wyjątek.

Przykład:

before(int value) : anyClassTaskCalled(value){

System.out.println("Wartosc" + value);...

}

background image

Aspekty

27

Aspekt przypomina zwykłą klasę Javy. Instancja aspektu jest pełnoprawnym

obiektem Javy i składnia jego obsługi jest analogiczna jak zwykłych obiektów.

Domyślnie pojedyncza instancja aspektu jest tworzona przez aplikację w momencie

uruchomienia i istnieje aż do jej zakończenia (singleton). Istnieje jednak możliwość

wybrania innego cyklu życia dla aspektu:

issingleton()

– singleton (domyślne)

perthis(Pointcut)

– nowa instancja dla każdego obiektu do którego odnosi

się referencja

this

w punkcie złączenia

pertarget(Pointcut)

– nowa instancja dla każdego obiektu, który jest celem

działania punktu złączenia

percflow(Pointcut)

– nowa instancja dla każdego wątku inicjowanego

w ramach punktu złączenia

background image

Aspekty

28

Kompletny przykład aspektu:

public aspect MyAspect issingleton(){

public pointcut myClassTaskCalled() : call(public void MyClass.foo());

public pointcut anyClassBarCalled(int number) : call(* *.bar(..)) &&

args(number);

before() : myClassTaskCalled(){

System.out.println("rada before() w MyAspect");

}

before(int value) : anyClassBarCalled(value) {

System.out.println("rada before() w MyAspect");

System.out.println("Parametr " + value);

}

}

background image

Przekroje statyczne

29

AspectJ może działać na statycznej strukturze aplikacji. Umożliwia to m. in.:

dodawanie nowych składowych do klasy

dodawanie nowych metod

deklarowanie nowych interfejsów

deklarowanie nowych zależności dziedziczenia

Przykład:

public aspect AddRunnable {

declare parents : MyClass implements Runnable;

public void MyClass.run(){

System.out.println("Implementacja metody Runnable.run()");

}

}

background image

Podsumowanie

30

Możliwość zmiany kodu klasy Javy w trakcie wykonywania programu wprowadza

wiele nowych możliwości przy tworzeniu oprogramowania. Zmiany takie można

wprowadzać bezpośrednio do kodu ładowanego przez

ClassLoader

'a lub poprzez

różne dostępne narzędzia (np. ASM). Wiele popularnych bibliotek korzysta z tej

techniki aby efektywnie realizować zadania (np. Hibernate). Na koncepcji

dynamicznej podmiany kodu opiera się jeden z paradygmatów tworzenia

oprogramowania – programowanie aspektowe.


Wyszukiwarka

Podobne podstrony:
JAVA 11 Dziedziczenie
java 22 11
Java Script (11)
143030393X {72191ACF} Fast Track to Sun Certified Java Programmer (SCJP) 5 0 Upgrade Exam [Tong 2006
Zarz[1] finan przeds 11 analiza wskaz
11 Siłowniki
11 BIOCHEMIA horyzontalny transfer genów
PKM NOWY W T II 11
wyklad 11
R1 11
CALC1 L 11 12 Differenial Equations
Prezentacje, Spostrzeganie ludzi 27 11
zaaw wyk ad5a 11 12
budzet ue 11 12
EP(11)
W 11 Leki działające pobudzająco na ośrodkowy układ

więcej podobnych podstron