Je druhé úterý v říjnu a tedy všem čtenářkám AbcLinuxu vše nejlepší k dnešnímu Dni Ady Lovelace (Ada Lovelace Day), tj. oslavy žen zabývajících se přírodními vědami, technologiemi, inženýrstvím a matematikou (STEM).
Byla vydána nová verze 2.47.0 distribuovaného systému správy verzí Git. Přispělo 83 vývojářů, z toho 28 nových. Přehled novinek v příspěvku na blogu GitHubu a v poznámkách k vydání.
Bylo vydáno OpenBSD 7.6. Opět bez písničky.
Programovací jazyk Python byl vydán v nové major verzi 3.13.0. Podrobný přehled novinek v changelogu.
Lze získat roota pouze se zapalovačem? Ano, lze.
Konference LinuxDays 2024 proběhne již tento víkend 12. a 13. října v Praze. Na programu je spousta zajímavých přednášek a workshopů, zástup zajímavých osobností a stánky řady projektů: Fedora, openSUSE, vpsFree.cz, Mozilla, brmlab, OpenAlt a mnoho dalších. Vstup zdarma.
Představeny byly oficiální Raspberry Pi microSD karty třídy A2 a silikonový kryt na Raspberry Pi 5.
OpenRazer byl vydán ve verzi 3.9.0. Jedná se o svobodný software, ovladač a démon, umožňující nastavovat klávesnice, notebooky, myši, podložky pod myš, keypady, sluchátka a další zařízení od společnosti Razer na GNU/Linuxu.
Byla vydána verze 3.6 multiplatformního integrovaného vývojového prostředí (IDE) pro rychlý vývoj aplikaci (RAD) ve Free Pascalu Lazarus (Wikipedie). Přehled novinek v poznámkách k vydání. Využíván je Free Pascal Compiler (FPC) 3.2.2.
Na čem aktuálně pracují vývojáři GNOME a KDE? Pravidelný přehled novinek v Týden v GNOME a Týden v KDE.
Ačkoliv je výbava Java Class Library s každou verzí lepší a lepší, ne vždy je dostatečná pro některé low level úlohy, nebo Java zkrátka neposkytuje (JITu navzdory) výkon, který nám může poskytnout pečlivě zoptimalizovaný kód. Dalším důvodem, proč JNI vzniklo, je napojení na knihovny systému a další platformně specifické věci – příkladem budiž SWT, které se v závislosti na aktuálním systému skrze JNI knihovny napojuje na nativní knihovny pro tvorbu GUI.
Nevýhodou použití JNI v této situaci je ztráta nezávislosti na hardwarové a softwarové platformě, neboť nativní knihovna musí být zkompilována například pro x86 a amd64 zvlášť a jednu knihovnu nemůžeme použít pro Windows a Linux zároveň. Je tedy důležité k JNI přistupovat s rozmyslem.
Opačný přístup je nasazování Javy v nativních aplikacích, což bude tématem pozdějších článků z tohoto seriálu. V této situaci nepředstavuje použití Javy žádné speciální komplikace, snad jen to, že samozřejmě musíme zajistit, aby na cílovém systému bylo k dispozici funkční a dostatečně aktuální JRE. Možná se ptáte, nač kazit rychlou nativní aplikaci tou „pomalou a rozežranou“ Javou. Java díky své mocnosti a dostupnosti nepřeberného množství knihoven představuje jednoho z kandidátů na tvorbu rozšíření do nativních aplikací. Snad nejznámější aplikací, kde se Java takto používá, je OpenOffice.org; nutno však podotknout, že za pomalostí tohoto kancelářského balíku není Java. Ba naopak, Java se dle mých zkušeností dokáže chovat přinejmenším stejně paměťově skromně jako jiné jazyky typické pro tento účel (Python a spol.).
Oproti (mnohdy interpretovaným) skriptovacím jazykům, které typicky obsazují místo jazyků pro rozšíření, Java nabízí vlastnosti silně typovaného jazyka, vyšší výkon díky JIT kompilaci a kromě toho garanci „stabilního zázemí“, kdy celá Java Class Library je zaručenou součástí každé instalace JRE. Uživatel si tak nemusí instalovat spousty wrapperů pro zvolený skriptovací jazyk a programátor nemusí řešit, co dělat, když knihovna nebude nainstalovaná, ačkoliv uznávám, že nenávist k desítkám instalovaných py a -ruby wrapperů je spíše mým osobním pohledem a záští.
JNI bohužel patří mezi API, která jsou Sunem a nyní Oraclem dosti zanedbávána. Na rozdíl od samotné Javy je dokumentace JNI dosti strohá (dva HTML soubory) a některé věci je nutné zjišťovat metodou pokus-omyl. Za poslední roky tato dokumentace dostala pouze "facelift", ale že nefunguje ani skákání na jednotlivé odstavce v dokumentu, to už nikoho nezajímalo. Bohužel i z hlediska používání rozhraní je třeba vždy myslet na to, že JNI si nikdy neporadí se špatným argumentem. Null pointer znamená pád, šáhnutí za konec pole znamená pád (žádné ArrayOutOfBoundsException) a překlep v názvu nativní metody při registraci znamená také pád, a to dokonce ještě s pěkným ohňostrojem.
Ne nadarmo se při psaní nativních knihoven doporučuje v knihovnách provádět holé minimum práce a zbytek napsat v Javě. Tímto pravidlem se řídí i samotný Sun/Oracle. Kromě nižšího rizika chyb je tu i zjevný důvod, že údržba takového kódu je ve výsledku snazší. Je to dobré pro přehlednost, neboť veškerá logika je pak na jediném místě a ne rozdělena mezi Java a C kód.
Nejprve se podíváme na to, jak proces načítání a používání nativních knihoven funguje na straně Javy. Nativní metody se v Javě vyznačují klíčovým slovem native
, taková jednoduchá třída tedy může vypadat následovně:
package test; public class TestNative { public static void javaMethod() { /* ... */ } public static native int nativeMethod(int myNumber); }
Pokud zavoláme metodu nativeMethod() v této situaci (kdy jsme nedodali odpovídající nativní kód), volání selže s výjimkou java.lang.UnsatisfiedLinkError: test.test.TestNative.nativeMethod(I)I
. Dalším krokem je nechat si vygenerovat hlavičkový soubor s deklaracemi pro jazyk C – k romu slouží konzolový nástroj javah
, jenž je součástí JDK. Javah pracuje nad zkompilovanými třídami, volitelně mu tedy předáváme classpath s umístěním těchto tříd.
$ javah -classpath ./build/classes test.TestNative $ ls *.h test_TestNative.h
V aktuálním adresáři nám vznikne hlavičkový soubor pojmenovaný podle balíčku a třídy. Soubor je přizpůsoben pro použití v C i C++.
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class test_TestNative */ #ifndef _Included_test_TestNative #define _Included_test_TestNative #ifdef __cplusplus extern "C" { #endif /* * Class: test_TestNative * Method: nativeMethod * Signature: (I)I */ JNIEXPORT jint JNICALL Java_test_TestNative_nativeMethod (JNIEnv *, jclass, jint); #ifdef __cplusplus } #endif #endif
Naše oči hned zabrousí k funkci void Java_test_TestNative_nativeMethod(JNIEnv *, jclass, jint)
, kterou máme naimplementovat. Uděláme si takový malý Hello world. Soubor test_TestNative.cpp:
#include "test_TestNative.h" #include <iostream> jint Java_test_TestNative_nativeMethod(JNIEnv* env, jclass myClass, jint myNumber) { std::cout << "Hello world!\n"; std::cout << "Argument value: " << myNumber << std::endl; return -myNumber; }
Nyní si z tohoto zdrojáku zkompilujeme sdílenou knihovnu. Samozřejmě by bylo lepší použít nějaký Makefile nebo rovnou použít autotools a podobné, ale pro jednoduchost ukážu příkaz přímo pro GCC s include cestami dle mého systému:
$ g++ -fPIC -shared \ > -I /usr/lib/jvm/java-6-sun-1.6.0.21/include \ > -I /usr/lib/jvm/java-6-sun-1.6.0.21/include/linux \ > -o /tmp/libtestnative.so test_TestNative.cpp
Teď naší javovskou třídu obohatíme o metodu main a necháme Javu načíst naší nativní knihovnu:
public static void main(String[] args) { System.loadLibrary("testnative"); int r = nativeMethod(123); System.out.println("The native method has returned " + r); }
Javovské System.loadLibrary respektuje zvyklosti z různých operačních systémů, na Linuxu je to prefix lib před názvem knihovny. System.loadLibrary("testnative")
tedy na Linuxu zkusí načíst libtestnative.so
. Poslední věc je Javě říci, kde má knihovnu hledat, a to nastavením java.library.path
(něco na způsob známého LD_LIBRARY_PATH
). Nyní tedy nazdar světe!
$ java -Djava.library.path=/tmp -cp build/classes test.TestNative Hello world! Argument value: 123 The native method has returned -123
Z ukázky tedy vidíme, že předávání a vracení primitivních typů je velmi jednoduché. Kromě argumentů, které předáváme z Javy, dostává naše nativní funkce ještě dva argumenty. Ten první – JNIEnv* env
– představuje bránu do javovského světa a je objektem, který budeme brzy velmi aktivně využívat. Jinak než pomocí JNIEnv nelze funkce JNI volat, snad jen s výjimkou funkce pro vytvoření JVM z nativní aplikace.
Druhý argument – jclass myClass
– dostávají pouze statické metody a jde o céčkovou reprezentaci instance java.lang.Class
, jež bychom v javovském kódu našli jako test.TestNative.class
.
V příštím díle se přesuneme od primitivních typů k objektům a zkusíme si vytvořit nějaký ten String
.
Nástroje: Tisk bez diskuse
Tiskni Sdílej:
třeba s nemazáním lokálních referencí v cyklu (padačka)To padalo kvůli překročení maximálního počtu referencí ve scope? Jinak si teď nedovedu představit, proč by to padalo.
Z tohto dovodu je dobre pouzivat zasadu, ze co najviac sa vyhybat nativnym knizniciam a ked ich uz musim pouzit tak izolovat izolovat a zasa izolovat a to najlepsie do separatneho procesu.Což má ale dopad na výkon, v některých případech může být i dost vysoký...
Pri desktopovych aplikaciach to este nemusi byt velky problem, ale ked vam padne cely server, tak to potom zacina zabava.Máš pravdu, ale je to trochu přehnané - takhle to mají všechny nativní aplikace a myslím si, že obecně jsou tyto na serverech v průměru v převaze
Podla mna drtiva vacsina web aplikacii su vytvarane v php,java,.net a python a to vacsinou bez pouzitia nativnych kniznic.Nevěděl jsem, že se bavíme o webových aplikacích...