Definim toate clasele pe care aplicația le utilizează pe java

Fără îndoială, toți cei care în CV-ul său indică experiența de a lucra la Java, cel puțin o dată în viața sa, a scris linii

Formularea problemei

Depășiți încărcătorul de clasă

Prima direcție care a venit în minte atunci când a rezolvat această problemă a fost să profite de posibilitățile de extindere a mecanismului de încărcare a claselor în Java. Pe acest subiect, a scris o mulțime de articole, inclusiv în limba rusă (link-uri la sfârșitul articolului).






Esența acestui mecanism este după cum urmează:

Cu toate acestea, în această etapă, a apărut deja primul concept al soluționării problemei:

  1. Implementați propriul încărcător de clasă, care înlocuiește încărcătorul de sistem, care, atunci când apelează metoda loadClass, va scrie pur și simplu numele de clasă într-un fișier și va transmite cererea pentru a încărca clasa în încărcătorul de sistem curent. În conformitate cu regula de delegare descrisă mai sus, aceasta ar trebui să vă permită captura tuturor claselor de utilizatori încărcabile, chiar dacă sunt încărcate de alți încărcătoare;
  2. Asigurați-vă că toate JVM-urile rulează pe aparat utilizează acest încărcător de clasă ca sistem.

Pentru a implementa al doilea element, trebuie rezolvate următoarele sarcini:

  • face ca clasa să fie vizibilă pentru toate JVM-urile care se execută. Includerea unei clase în întreaga clasă a setului de componente ale aplicației este incomodă, consumatoare de timp și irațională în ceea ce privește extinderea sistemului. Mai mult decât atât, există o soluție mai frumoasă - de a pune clasa bootloader în folderul lib / ext JRE. Clasele din acest dosar sunt puse automat la dispoziție fără a le adăuga la calea de clasă (după cum sa menționat mai sus, acestea sunt încărcate de încărcătorul de extensie la pornirea JVM);
  • stabilit pentru toate JVM java.system.class.loader proprietate sistem - de la linia de comandă, puteți face acest lucru: java -Djava.system.class.loader = imya.klassa.zagruzchika HelloWolrd
  • forțați direct toate JVM-urile să ruleze cu parametrul necesar - Djava.system.class.loader. După cum sa dovedit, există și o soluție elegantă pentru aceasta - trebuie să utilizați o variabilă specială de mediu, valoarea căreia este adăugată automat la parametrii de pornire ai oricărui JVM. În timpul căutării, s-au găsit două variabile care ar putea fi responsabile de această caracteristică: JAVA_OPTS și JAVA_TOOL_OPTIONS. Cu toate acestea, niciunul dintre articole nu a dat un răspuns clar la întrebarea care este diferența dintre aceste două variabile? Răspunsul la această întrebare a fost decis să fie găsit prin experiență. În timpul experimentului, sa constatat că prezenta „magic“ este JAVA_TOOL_OPTIONS variabilă, a căror valoare se adaugă automat parametrii pentru a rula orice declanșat HotSpot JVM. Și JAVA_OPTS este rezultatul unui acord implicit între dezvoltatorii de aplicații Java diferite. Această variabilă utilizată în mod explicit de multe script-uri (de exemplu, startup.sh/startup.bat pentru a rula Apache Tomcat), dar nu există nici o garanție că acest lucru va fi de a folosi toate dezvoltatorii de script variabilă.






Deci, se face, încărcătorul este compilat și plasat în lib / ext, valoarea JAVA_TOOL_OPTIONS de mediu stabilite, porniți aplicația, munca, deschide jurnalul și a vedea ... o listă slaba a celor zece clase, inclusiv de sistem și mai multe clase de terțe părți. Aici a trebuit să ne amintim de implementarea non-obligatorie a regulii de delegare a descărcării, precum și de privire la codul sursă pentru Apache Ant și Tomcat. După cum sa dovedit, aceste aplicații folosesc propriul încărcător de clasă. Acest lucru, pe de o parte, le-a permis parțial să dobândească funcționalitatea lor puternică. Cu toate acestea, indiferent de motiv, dezvoltatorii acestor produse au decis să nu adere la normele recomandate de delegare incarcator de boot și scrise de ei nu se întoarce întotdeauna la părinții lor înainte de a descărca clasa următoare. De aceea, nu știm aproape nimic despre clasele de bootloader încărcate Tomcat-lea-lea și Ant.
Astfel, metoda descrisă nu permite capturarea tuturor claselor necesare, în special având în vedere varietatea serverelor de aplicații utilizate - cine știe cum dezvoltatorii serverului de aplicații client au tratat regula de delegare a încărcării.

Încearcă numărul doi. Aplicați instrumentele de clasă.

  1. Scrieți clasa transformator implementând metoda ClassFileTransformer.transform. care, cu toate acestea, nu va efectua nici o transformare, ci va înregistra doar numele clasei încărcate în fișier.
  2. Din nou, trebuie să ne asigurăm că clasa pe care o scriem se conectează la orice aplicație Java care este lansată.

Codul sursă al clasei transformatorului este prezentat mai jos:

Aici este necesar să se explice mecanismul de utilizare a claselor de transformatoare. Pentru a conecta o astfel de clasă la aplicație, avem nevoie de așa-numita clasă premain, adică clasa care conține metoda public static void premain (String paramString, Instrumentation paramInstrumentation). Din numele metodei, este clar că se numește înainte ca metoda principală să fie apelată. În acest moment, puteți conecta clasele de transformatoare la aplicație utilizând metoda addTransformer a interfeței java.lang.instrument.Instrumentation. Astfel, clasa de mai sus este atât o clasă de transformatoare cât și o clasă de premain. Pentru această clasă poate fi utilizat, acesta trebuie să fie plasat într-un fișier JAR, care se manifestă (META-INF / fișierul MANIFEST.MF) conține parametrul Premain-Class indică numele complet premain-clasă, în cazul nostru Premain-Class: com.test .LoggingClassFileTransformer. Apoi, trebuie să specificați calea completă la această arhivă utilizând opțiunea -javaagent la pornirea JVM. Aici, din nou, variabila JAVA_TOOL_OPTIONS vine în ajutorul nostru.
Deci, clasa este scris, compilat, ambalate împreună cu un manifest în JAR, variabila de mediu JAVA_TOOL_OPTIONS = -javaagent: „calea către LoggingClassFileTransformer.jar“ este specificat, aplicația se execută, log recoltat, profit!

concluzie

Deci, ce concluzii se pot trage după finalizarea lucrărilor la proiect:

Lista surselor utilizate

Articole despre încărcătoare de clasă în Java:

Alte link-uri utile:







Trimiteți-le prietenilor: