[java] Dynamische compilatie

Pagina: 1
Acties:

  • Count
  • Registratie: Augustus 2000
  • Laatst online: 10-08-2023
Hey,

ik bouw een spelletje (voor mijn werk, jaja) en daarbij komen een heleboel statistieken kijken. Tijdens de ontwikkelingsfase gaat er een heleboel getweaked worden aan deze stats. Dus de stats in een externe file komen zodat het zonder te compilen aangepast kan worden.

Omdat ik lui ben wou ik deze stats in een java filetje proppen die dan runtime gecompiled word. Dit scheelt mij een parser schrijven of XML libraries e.d. gebruiken.

Filetje ziet er zo uit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Script extends ScriptedEvents {
    public void registerUnitTypes(){
        System.out.println("Running startup script");

        // Tank definition
        UnitType tank = new UnitType();
        tank.name = "Tank";
        tank.roadMovement = 3;
        tank.landMovement = 3;
        tank.shotDamage = 3;
        tank.surroundDamage = 1;
        tank.shotDistance = 3;
        tank.credits = 10;
        tank.imageName = "tank.jpg";
        UnitType.register(tank);


Alleen ik krijg het niet voor elkaar om deze .java file runtime te compilen. ClassLoader werkt alleen op bytecode en da's dus niet gewenst. De Compiler class documentatie wordt ik ook niet wijzer van.

Great minds think in parallel gutters.


  • PostbodeSiemen
  • Registratie: Maart 2000
  • Laatst online: 19-08-2024
http://www-106.ibm.com/de...edu/j-dw-javaclass-i.html

Staat een voorbeeld in. Wel ff registreren maar dat moet niet te veel moeite zijn.

[ Voor 36% gewijzigd door PostbodeSiemen op 02-07-2003 01:00 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 01:56
Een van de beste OO-ontwerpprincipes is het opdelen van de identiteit van objecten in gedrag (methoden) en eigenschappen (attributen). Voor variaties in gedrag maak je aparte klassen aan, voor variaties in eigenschappen gebruik je dezelfde klasse met verschillend geinitialiseerde attributen. Statistieken van eenheden vallen typisch in de laatste categorie en die kun je dus beter niet als Java code modelleren, maar uitsluitend als de waarden waarmee bestaande code wordt geinstantieerd.

Ik denk dat je je probleem dus voldoende kunt oplossen door geen Java code dynamisch te laden, maar slechts de eigenschappen van de objecten die je met je statische Java code implementeert. In plaats van dynamische code te schrijven die nieuwe UnitType objecten aanmaakt (zoals in jouw voorbeeld) zou je dus de statistieken van de UnitType's in een XML bestand kunnen stoppen (zodat daar eenvoudig aan getweaked kan worden) en die statistieken bij het opstarten inladen (met vergelijkbare code als je nu al doet, maar dan door de gegevens met een XML parser uit je configuratiebestand te halen).

Als je echt, echt, echt de Java code wilt varieren, dan kan dat natuurlijk ook, maar eigenlijk zie ik niet direct in waarom je dan ook niet even de moeite zou willen nemen om die code naar class files te compileren.

[ Voor 9% gewijzigd door Soultaker op 02-07-2003 01:29 ]


  • Count
  • Registratie: Augustus 2000
  • Laatst online: 10-08-2023
PostbodeSiemen schreef op 02 July 2003 @ 00:59:
http://www-106.ibm.com/de...edu/j-dw-javaclass-i.html

Staat een voorbeeld in. Wel ff registreren maar dat moet niet te veel moeite zijn.
Heh, ik kom er niet in;
Network Difficulties
We are sorry, but we are experiencing network difficulties.
Please go back, reload the previous page and try again.

If the problem persists please try again at a later time or use the "Contact IBM" option below to report the problem.
Soultaker, ik wil het liefst geen XML gebruiken voor de stats. Want ik verwacht dat later in het project ik sowieso dynamische compilatie nodig heb als elke Map zijn eigen scripted events krijgt.

Great minds think in parallel gutters.


  • Count
  • Registratie: Augustus 2000
  • Laatst online: 10-08-2023
PostbodeSiemen, bedankt. In de tutorial staat het antwoord:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
// Start up the compiler
    Process p = Runtime.getRuntime().exec( "javac "+javaFile );

    // Wait for it to finish running
    try {
      p.waitFor();
    } catch( InterruptedException ie ) { System.out.println( ie ); }

    // Check the return code, in case of a compilation error
    int ret = p.exitValue();

    // Tell whether the compilation worked
    return ret==0;


Hoewel ik het persoonlijk wel beroerd vind dat dit de enige manier is om runtime te compilen onder java...

Great minds think in parallel gutters.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 01:56
Tja, dan moet je een taal gebruiken die een compiler in de runtime libraries heeft zitten, zoals Python. Die compileert de broncode wanneer de bijbehorende gecompileerde code ouder is of niet bestaat. Maar goed, aan die opmerking heb jij natuurlijk niets, nu. :)

Java doet uitsluitend aan het dynamisch laden van klassen, voor zover ik weet, en je kunt vanuit de runtime environment dan ook niet compileren. Als je echt Java-code wilt gebruiken, waarom kun je dan eigenlijk niet handmatig die code compileren? Je zult die code ook handmatig moeten schrijven, neem ik aan (dat zijn je "scripted events") anders kun je echt beter de gegevens in een dataformaat wegschrijven.

[ Voor 6% gewijzigd door Soultaker op 02-07-2003 12:21 ]


  • MisterData
  • Registratie: September 2001
  • Laatst online: 19:41
En serializen, is dat geen optie?

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 17:28

alienfruit

the alien you never expected

Fantastisch Developerworks en zijn tijdschrift die betalen $1 per woord die je schrijft; alleen is er wel een limit qua worden (dacht dat het rond de 1600-2000 woorden was).

  • PommeFritz
  • Registratie: Augustus 2001
  • Laatst online: 10-07 04:13

PommeFritz

...geen friet

Kijk eens naar de com.sun.tools.javac package in de tools.jar van je JDK. De Javac compiler is niet gedocumenteerd voor zover ik weet, maar een beetje decompilen van de classes hier moet je toch een eind kunnen helpen. Kijk anders ook eens naar hoe b.v. Tomcat de JSP code dynamisch compileert? Tomcat is open source dus je kunt gewoon de JSP compiler (Jasper heet die geloof ik) bestuderen.

edit: hm ik lees net dat Jasper gebruik maakt van Ant om te compileren. Dat treft, want dat is ook open source.

[ Voor 16% gewijzigd door PommeFritz op 02-07-2003 20:41 ]

FireFox - neem het web in eigen hand


Verwijderd

Het is heel simpel om de javac compiler aan te roepen vanuit je code. Het volgende stukje code doet dat.

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
   public boolean usefullMethodName() {

         // where do we want to put the compiled script
         File scriptDest = new File( SCRIPTDESTINATION );
         if ( !scriptDest.exists() ) {
            // target dir does not exist. Create it.
            scriptDest.mkdir();
         }

         // used for capturing the stndErr.
         ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
         PrintStream st = new PrintStream( byteStream );

         // used to store the old printstream
         PrintStream stErrOld = System.err;

         // capture the errors
         System.setErr( st );

         // get an instance of the compiler.
         com.sun.tools.javac.Main mn = new com.sun.tools.javac.Main();

         // get the classPath
         String classPath = getClassPath();

         // setup the arguments for the compiler
         String[] argsCompile = {"-g"
               , "-classpath"
               , classPath
               , "-d"
               , SCRIPTDESTINATION
               , SCRIPTLOCATION + SCRIPTNAME
               };

         // compile the file.
         mn.compile( argsCompile );

         // get the errorStrings
         st.flush();

         // setting the error printstream back to the original one
         System.setErr( stErrOld );

         return parseCompilerMessages( byteStream.toString() );
      } else {
         // classfile is already compiled and loaded. so no errors found
         return false;
      }
   }


Kleine toelichting, alles in hoofdletters moet je zelf maar even invullen, die bepalen waar alles terecht komt. De getClassPath method returned een String die het hele classpath voorsteld. Die staat hier niet bij, maar als we op een windows systeem zitten returned die methode het classpath gescheiden door ';' en op unix door ':'

Oh bijna vergeten, je moet wel zorgen dat tools.jar van je sdk in je classpath staat.

[ Voor 4% gewijzigd door Verwijderd op 03-07-2003 09:17 ]


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Soultaker schreef op 02 juli 2003 @ 12:21:
Tja, dan moet je een taal gebruiken die een compiler in de runtime libraries heeft zitten, zoals Python. Die compileert de broncode wanneer de bijbehorende gecompileerde code ouder is of niet bestaat. Maar goed, aan die opmerking heb jij natuurlijk niets, nu. :)
http://www.jython.org ;)

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 17:28

alienfruit

the alien you never expected

Wat is het nut van dynamische compilatie behalve een lekkere hack; omdat je geen zin hebt om ergens meer tijd aan te besteden?

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
alienfruit: Wat is het nut van dynamische compilatie behalve een lekkere hack; omdat je geen zin hebt om ergens meer tijd aan te besteden?
Runtime code generatie kan heel nuttig zijn en code die je at runtime genereert moet natuurlijk ook gecompileerd worden. Je kan bijvoorbeeld code genereren ter efficientie bij het uitvoeren van een zware operatie (interpretatie is meestal trager). Bekende voorbeelden zijn dan bijvoorbeeld regexp engines.

Zie ook dit topic:
[rml][ java] meteen bytecode of eerst source.[/rml]

Ik noem daar de compiling classloader, welke Java sources kan laden en pas at runtime compileert naar bytecode. Er is daar een uitgebreid artikel te vinden over hoe je de compiler aanroept.

Zie ook JSR 199: Java Compiler API. Helaas is dit pas gepland voor 1.5. Uiteraard had er allang iets dergelijks moeten zijn: het at runtime compileren van code en een gestandaardiseerde AST is een basisvoorwaarde.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Toch maar ff een directe link voor luie mensen ;) .

http://www.panix.com/~mito/articles/#classloader

Edit: ik zie trouwens dat dit artikel al genoemd was. Beter lezen |:( . Sorry! ;) .

[ Voor 30% gewijzigd door mbravenboer op 03-07-2003 10:47 ]

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 17:28

alienfruit

the alien you never expected

Hmm. Okay. Het kan dus handig zijn voor bepaalde zware processen; maar Run-time code generatie; ik heb even snel gekeken op Google; volgens mij is die generatie gedoe een stuk makkelijker in .NET en Java dan bijv. in C++/C of Delphi. Waarschijnlijk omdat Java/.NET bytecode/CLR hebben als tussen stap :?

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

alienfruit schreef op 03 juli 2003 @ 10:39:
Hmm. Okay. Het kan dus handig zijn voor bepaalde zware processen; maar Run-time code generatie; ik heb even snel gekeken op Google; volgens mij is die generatie gedoe een stuk makkelijker in .NET en Java dan bijv. in C++/C of Delphi. Waarschijnlijk omdat Java/.NET bytecode/CLR hebben als tussen stap :?
Het voordeel aan bytecode is dat het nog relatief dicht bij de source ligt, dus het valt ook vrij makkelijk te genereren. De jitter (Just In Time compiler) die gaat het dan wel echt compileren naar iets wat jouw computer leuk vind om uit te voeren.

  • Count
  • Registratie: Augustus 2000
  • Laatst online: 10-08-2023
Wat is het nut van dynamische compilatie behalve een lekkere hack; omdat je geen zin hebt om ergens meer tijd aan te besteden?
Ik wou dynamisch compilen omdat andere mensen (niet programmeurs) ook een beetje willen tweaken aan bepaalde algoritmes. In het spelletje is er bijvoorbeeld een berekening voor combat-damage. Deze is heel uitgebreid en moet regelmatig aangepast worden. Daarom wil ik hem extern maken. Dat lukt dus heel goed met dit systeem. Nu kan iemand gewoon Script.java editen, het programma opnieuw opstarten en verder testen zonder allerlei batchfiletjes of wat ook te gebruiken.

En ik stel me voor dat ook na de release van het spelletje is het handig om bepaalde dingen scripted te hebben. Zo kan er in principe een mod-community komen (ok, gebeurt niet maar het kan). :)

Sosume: bedankt voor je elegantere oplossing.

Great minds think in parallel gutters.


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Als je extern scripten wilt toelaten moet je echt eens kijken naar : http://www.jython.org

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 17:28

alienfruit

the alien you never expected

maar is het niet mogelijk omdat je java zelf gebruikt, dat ze gaan aankloten?
Zelf zou ik gewoon binnen een uurtje me eigen script engine in elkaar knutselen(in java zal het niet lukken in uur overigens ;))

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Waarom zou je een eigen script engine in elkaar prutsen als al vele anderen dat gedaan hebben?

Er zijn fantastische script talen (Python ;) ) en engines (Jython ;) ) die je kan gebruiken om je applicatie uit te breiden of te configuren via scripts. Jython wordt daar al enorm veel voor gebruikt, sommige applicaties zijn zelfs voor grote delen hierin geschreven (Jext gebruikt het bijvoorbeeld intensief).

Zelf dingen doen is natuurlijk heel educatief, maar over het algemeen schiet je produkt er niet erg veel mee op: je kan het over het algemeen niet beter dan mensen die iets tot hun kernactiviteit hebben gemaakt. Python is daarvan een prima voorbeeld.

Overigens onderschat je nog wel wat er allemaal nodig is voor een beschaafde script taal en engine. Alleen met het ontwerpen van een taal en het schrijven van een parser ben je al wel een paar dagen bezig als je iets meer wilt dan variabelen en rekenkundige expressies. Laat staan dat je echt leuke dingen kan verwerken, die wel in Python zitten.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • Count
  • Registratie: Augustus 2000
  • Laatst online: 10-08-2023
Ik vind dit persoonlijk wel een elegante oplossing. Java is toch een mooie taal, hoef je niet persé iets aan te hangen lijkt me. Scheelt ook weer dat je niet allerlei libraries hoeft bij te leveren zodat het programma compact blijft (belangrijke eis voor mij).

Je kunt altijd de security manager veranderen (dacht ik) als je scripted spul gaat draaien.

Great minds think in parallel gutters.


Verwijderd

Tja als je toch meer richting een script engine will zou ik idd maar eens kijken naar Jython. Wil je het meer op java houden kijk dan eens naar beanshell. Dan kan je je script gewoon schrijven in Java maar heb je allemaal wat meer mogelijkheden om het netjes af te handelen.

Als je beanshell gebruikt hoef je alleen nog maar het volgende te doen om een script te runnen.

Java:
1
2
3
4
5
6
7
8
9
10
11
12
    // get new interpreter 
    Interpreter bshInterpreter = new Interpreter();

    // run the script
         try {
            bshInterpreter.eval(THESCRIPTASONEBIGSTRINGORSTREAM);
        } catch (EvalError bshError) {

            // an error occured running the script.
            someErrorHandling();

        }


Hoef je zelf tenminste niet allemaal compile stappen te doen.

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 17:28

alienfruit

the alien you never expected

Nou ik zou zelf voor een script engine omdat ik er al bergen heb geschreven; en dus veel meer ervaring ermee heb dan die compiler-klasses in Java. Maar ik ga er zeker eens naar kijken in de vakantie :)

  • Count
  • Registratie: Augustus 2000
  • Laatst online: 10-08-2023
alienfruit, je moet toch toegeven dat dat veel meer werk is. Ik heb ook wel een script interpreter gebouwd eens maar dat kost je toch echt wel meer als een paar uur. Bovendien bied het dan nog niet alle functionaliteit van Java.

Daarbij zie ik niet echt het voordeel behalve dat je zelf de syntax bepaalt.

Great minds think in parallel gutters.


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Countach :Daarbij zie ik niet echt het voordeel behalve dat je zelf de syntax bepaalt.
En zelfs daarvan is het de vraag of het een voordeel is ;) .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment

Pagina: 1