VM.reload can now reload a class in existing virtual machine
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 14 Oct 2013 16:44:55 +0200
changeset 1373c4e57ec5f0df
parent 1372 cc58b30499e5
child 1374 bc2319ca9c17
VM.reload can now reload a class in existing virtual machine
rt/emul/mini/src/main/java/org/apidesign/vm4brwsr/api/VM.java
rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java
rt/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java
rt/vm/src/test/java/org/apidesign/vm4brwsr/BytesLoader.java
rt/vm/src/test/java/org/apidesign/vm4brwsr/Hello.java
rt/vm/src/test/java/org/apidesign/vm4brwsr/ReloadingTest.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/rt/emul/mini/src/main/java/org/apidesign/vm4brwsr/api/VM.java	Mon Oct 14 16:44:55 2013 +0200
     1.3 @@ -0,0 +1,47 @@
     1.4 +/**
     1.5 + * Back 2 Browser Bytecode Translator
     1.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     1.7 + *
     1.8 + * This program is free software: you can redistribute it and/or modify
     1.9 + * it under the terms of the GNU General Public License as published by
    1.10 + * the Free Software Foundation, version 2 of the License.
    1.11 + *
    1.12 + * This program is distributed in the hope that it will be useful,
    1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.15 + * GNU General Public License for more details.
    1.16 + *
    1.17 + * You should have received a copy of the GNU General Public License
    1.18 + * along with this program. Look for COPYING file in the top folder.
    1.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    1.20 + */
    1.21 +package org.apidesign.vm4brwsr.api;
    1.22 +
    1.23 +import java.io.IOException;
    1.24 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
    1.25 +
    1.26 +/** Utility methods to talk to the Bck2Brwsr virtual machine.
    1.27 + *
    1.28 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    1.29 + * @since 0.9
    1.30 + */
    1.31 +public final class VM {
    1.32 +    private VM() {
    1.33 +    }
    1.34 +
    1.35 +    /** Takes an existing class and replaces its existing byte code 
    1.36 +     * with new one.
    1.37 +     * 
    1.38 +     * @param clazz existing class to reload
    1.39 +     * @param byteCode new bytecode
    1.40 +     * @throws IOException an exception is something goes wrong
    1.41 +     */
    1.42 +    public static void reload(Class<?> clazz, byte[] byteCode) throws IOException {
    1.43 +        reloadImpl(clazz.getName(), byteCode);
    1.44 +    }
    1.45 +    
    1.46 +    @JavaScriptBody(args = { "name", "byteCode" }, body = "vm._reload(name, byteCode);")
    1.47 +    private static void reloadImpl(String name, byte[] byteCode) throws IOException {
    1.48 +        throw new IOException();
    1.49 +    }
    1.50 +}
     2.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Sat Oct 12 19:26:45 2013 +0200
     2.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Mon Oct 14 16:44:55 2013 +0200
     2.3 @@ -153,6 +153,12 @@
     2.4              + "      throw 'Cannot initialize the bck2brwsr VM twice!';\n"
     2.5              + "    }\n"
     2.6              + "    vm.loadClass = loader.loadClass;\n"
     2.7 +            + "    vm._reload = function(name, byteCode) {;\n"
     2.8 +            + "      var attr = name.replace__Ljava_lang_String_2CC('.','_');\n"
     2.9 +            + "      delete vm[attr];\n"
    2.10 +            + "      return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
    2.11 +            + "        reload__Ljava_lang_Object_2Ljava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2_3B(loader, name, args, byteCode);\n"
    2.12 +            + "    };\n"
    2.13              + "    vm.loadBytes = function(name) {\n"
    2.14              + "      return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
    2.15              + "        loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n"
     3.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java	Sat Oct 12 19:26:45 2013 +0200
     3.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java	Mon Oct 14 16:44:55 2013 +0200
     3.3 @@ -42,6 +42,11 @@
     3.4      throws IOException, ClassNotFoundException {
     3.5          return new VMLazy(loader, arguments).load(name, false);
     3.6      }
     3.7 +
     3.8 +    static Object reload(Object loader, String name, Object[] arguments, byte[] arr) 
     3.9 +    throws IOException, ClassNotFoundException {
    3.10 +        return new VMLazy(loader, arguments).defineClass(arr, name, false);
    3.11 +    }
    3.12      
    3.13      static byte[] loadBytes(Object loader, String name, Object[] arguments) throws Exception {
    3.14          return Zips.loadFromCp(arguments, name);
    3.15 @@ -54,7 +59,11 @@
    3.16          if (arr == null) {
    3.17              throw new ClassNotFoundException(name);
    3.18          }
    3.19 -//        beingDefined(loader, name);
    3.20 +        
    3.21 +        return defineClass(arr, name, instance);
    3.22 +    }
    3.23 +
    3.24 +    private Object defineClass(byte[] arr, String name, boolean instance) throws IOException {
    3.25          StringBuilder out = new StringBuilder(65535);
    3.26          out.append("var loader = arguments[0];\n");
    3.27          out.append("var vm = loader.vm;\n");
     4.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/BytesLoader.java	Sat Oct 12 19:26:45 2013 +0200
     4.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/BytesLoader.java	Mon Oct 14 16:44:55 2013 +0200
     4.3 @@ -21,20 +21,19 @@
     4.4  import java.io.InputStream;
     4.5  import java.net.URL;
     4.6  import java.util.Enumeration;
     4.7 -import java.util.Set;
     4.8 -import java.util.TreeSet;
     4.9  
    4.10  /**
    4.11   *
    4.12   * @author Jaroslav Tulach <jtulach@netbeans.org>
    4.13   */
    4.14  public final class BytesLoader {
    4.15 -    private static Set<String> requested = new TreeSet<String>();
    4.16 +    private static final StringArray requested = new StringArray();
    4.17  
    4.18      public byte[] get(String name) throws IOException {
    4.19 -        if (!requested.add(name)) {
    4.20 +        if (requested.contains(name)) {
    4.21              throw new IllegalStateException("Requested for second time: " + name);
    4.22          }
    4.23 +        requested.add(name);
    4.24          byte[] arr = readClass(name);
    4.25          /*
    4.26          System.err.print("loader['" + name + "'] = [");
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/Hello.java	Mon Oct 14 16:44:55 2013 +0200
     5.3 @@ -0,0 +1,35 @@
     5.4 +/**
     5.5 + * Back 2 Browser Bytecode Translator
     5.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     5.7 + *
     5.8 + * This program is free software: you can redistribute it and/or modify
     5.9 + * it under the terms of the GNU General Public License as published by
    5.10 + * the Free Software Foundation, version 2 of the License.
    5.11 + *
    5.12 + * This program is distributed in the hope that it will be useful,
    5.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.15 + * GNU General Public License for more details.
    5.16 + *
    5.17 + * You should have received a copy of the GNU General Public License
    5.18 + * along with this program. Look for COPYING file in the top folder.
    5.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    5.20 + */
    5.21 +package org.apidesign.vm4brwsr;
    5.22 +
    5.23 +import java.io.IOException;
    5.24 +
    5.25 +/**
    5.26 + *
    5.27 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    5.28 + */
    5.29 +public class Hello {
    5.30 +    public static String hello() {
    5.31 +        return "Hello World!";
    5.32 +    }
    5.33 +    
    5.34 +    public static Object reloadYourSelf(byte[] arr) throws IOException {
    5.35 +        org.apidesign.vm4brwsr.api.VM.reload(Hello.class, arr);
    5.36 +        return null;
    5.37 +    }
    5.38 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/ReloadingTest.java	Mon Oct 14 16:44:55 2013 +0200
     6.3 @@ -0,0 +1,72 @@
     6.4 +/**
     6.5 + * Back 2 Browser Bytecode Translator
     6.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     6.7 + *
     6.8 + * This program is free software: you can redistribute it and/or modify
     6.9 + * it under the terms of the GNU General Public License as published by
    6.10 + * the Free Software Foundation, version 2 of the License.
    6.11 + *
    6.12 + * This program is distributed in the hope that it will be useful,
    6.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.15 + * GNU General Public License for more details.
    6.16 + *
    6.17 + * You should have received a copy of the GNU General Public License
    6.18 + * along with this program. Look for COPYING file in the top folder.
    6.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    6.20 + */
    6.21 +package org.apidesign.vm4brwsr;
    6.22 +
    6.23 +import org.testng.annotations.BeforeClass;
    6.24 +import org.testng.annotations.AfterClass;
    6.25 +import org.testng.annotations.Test;
    6.26 +
    6.27 +/**
    6.28 + *
    6.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    6.30 + */
    6.31 +public class ReloadingTest {
    6.32 +    private static TestVM code;
    6.33 +    
    6.34 +    @Test public void verifyUsageOf() throws Exception {
    6.35 +        code.execCode("First hello", 
    6.36 +            Hello.class, "hello__Ljava_lang_String_2",
    6.37 +            "Hello World!"
    6.38 +        );
    6.39 +
    6.40 +        byte[] arr = BytesLoader.readClass("org/apidesign/vm4brwsr/Hello.class");
    6.41 +        for (int i = 0; i < arr.length; i++) {
    6.42 +            if (arr[i] == 'H' && arr[i + 1] == 'e' && arr[i + 2] == 'l') {
    6.43 +                arr[i] = 'A';
    6.44 +                arr[i + 1] = 'h';
    6.45 +                arr[i + 2] = 'o';
    6.46 +                arr[i + 3] = 'y';
    6.47 +                arr[i + 4] = ' ';
    6.48 +                break;
    6.49 +            }
    6.50 +        }
    6.51 +        
    6.52 +        code.execCode("Redefine class",
    6.53 +            Hello.class, "reloadYourSelf__Ljava_lang_Object_2_3B",
    6.54 +            null, arr
    6.55 +        );
    6.56 +
    6.57 +        code.execCode("Second hello", 
    6.58 +            Hello.class, "hello__Ljava_lang_String_2",
    6.59 +            "Ahoy  World!"
    6.60 +        );
    6.61 +    }
    6.62 +    
    6.63 +    
    6.64 +    @BeforeClass 
    6.65 +    public static void compileTheCode() throws Exception {
    6.66 +        code = TestVM.compileClass(
    6.67 +            "org/apidesign/vm4brwsr/Hello");
    6.68 +    }
    6.69 +    @AfterClass
    6.70 +    public static void releaseTheCode() {
    6.71 +        code = null;
    6.72 +    }
    6.73 +    
    6.74 +}
    6.75 +