jmarranz / relproxy

Simple Java and Groovy hot class reloader and Java based shell and scripting
107 stars 13 forks source link

Doesn't seem to work on Java8 #7

Open maxott opened 7 years ago

maxott commented 7 years ago

Just tried to recreate the example at the end of the manual and reloading won't work:

Reloaded com.mycompany.app.TestListener@6a41eaa2 - class com.mycompany.app.TestListener Calling method: public abstract void com.mycompany.app.OutputListener.write(java.io.PrintStream) - [Ljava.lang.Object;@7cd62f43
OLD: com.mycompany.app.TestListener@1e88b3c - class com.mycompany.app.TestListener
uppercase
lowercase
NEW: com.mycompany.app.TestListener@6a41eaa2 - class com.mycompany.app.TestListener
java.lang.IllegalArgumentException: object is not an instance of declaring class
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.mycompany.app.App$2.onReload(App.java:97)
    at com.innowhere.relproxy.impl.GenericProxyInvocationHandler.invoke(GenericProxyInvocationHandler.java:40)
    at com.sun.proxy.$Proxy0.write(Unknown Source)
    at com.mycompany.app.RelProxyBuiltinImpl.runLoop(RelProxyBuiltinImpl.java:95)
    at com.mycompany.app.App.mainTest(App.java:191)
    at com.mycompany.app.App.<init>(App.java:41)
    at com.mycompany.app.App.main(App.java:31)

I slightly changed the RelProxyOnReloadListener implementation to:

        RelProxyOnReloadListener proxyListener = new RelProxyOnReloadListener() {
            public void onReload(Object objOld, Object objNew, Object proxy, Method method, Object[] args) {
                System.out.println("Reloaded " + objNew + " - " + objNew.getClass() + " Calling method: " + method + " - " + args);

                try {
                  System.out.println("OLD: " + objOld + " - " + objOld.getClass());
                  method.invoke(objOld, args);
                  System.out.println("NEW: " + objNew + " - " + objNew.getClass());
                  method.invoke(objNew, args);
                } catch (Exception e) {
                  e.printStackTrace();
                }

            }
        };

It appears that in my environment, the Method object also changes on the recompile.

$ java -version
java version "1.8.0_65"
Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)

Any ideas on how that could be solved? Am I doing something wrong?

jmarranz commented 7 years ago

Hello Max

I haven't tried Java 8 and RelProxy

Do the following: run the example with Java 7, do the same with Java 8 and compare.

Best wishes

Jose Maria Arranz

On 09/10/2016 8:02, Max Ott wrote:

Just tried to recreate the example at the end of the manual and reloading won't work:

|Reloaded com.mycompany.app.TestListener@6a41eaa2 - class com.mycompany.app.TestListener Calling method: public abstract void com.mycompany.app.OutputListener.write(java.io.PrintStream) - [Ljava.lang.Object;@7cd62f43 OLD: com.mycompany.app.TestListener@1e88b3c - class com.mycompany.app.TestListener uppercase lowercase NEW: com.mycompany.app.TestListener@6a41eaa2 - class com.mycompany.app.TestListener java.lang.IllegalArgumentException: object is not an instance of declaring class at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:483) at com.mycompany.app.App$2.onReload(App.java:97) at com.innowhere.relproxy.impl.GenericProxyInvocationHandler.invoke(GenericProxyInvocationHandler.java:40) at com.sun.proxy.$Proxy0.write(Unknown Source) at com.mycompany.app.RelProxyBuiltinImpl.runLoop(RelProxyBuiltinImpl.java:95) at com.mycompany.app.App.mainTest(App.java:191) at com.mycompany.app.App.(App.java:41) at com.mycompany.app.App.main(App.java:31) |

I slightly changed the |RelProxyOnReloadListener| implementation to:

|RelProxyOnReloadListener proxyListener = new RelProxyOnReloadListener() { public void onReload(Object objOld, Object objNew, Object proxy, Method method, Object[] args) { System.out.println("Reloaded " + objNew + " - " + objNew.getClass() + " Calling method: " + method + " - " + args); try { System.out.println("OLD: " + objOld + " - " + objOld.getClass()); method.invoke(objOld, args); System.out.println("NEW: " + objNew + " - " + objNew.getClass()); method.invoke(objNew, args); } catch (Exception e) { e.printStackTrace(); } } }; |

It appears that in my environment, the |Method| object also changes on the recompile.

|$ java -version java version "1.8.0_65" Java(TM) SE Runtime Environment (build 1.8.0_65-b17) Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode) |

Any ideas on how that could be solved? Am I doing something wrong?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/jmarranz/relproxy/issues/7, or mute the thread https://github.com/notifications/unsubscribe-auth/ACwLXE8Rqg5Q4B6W5CIZD_9948LvGT0Hks5qyIOIgaJpZM4KR6sR.

maxott commented 7 years ago

Tried the same with java7 (on a Mac) - same result

$ java -version
java version "1.7.0_75"
Java(TM) SE Runtime Environment (build 1.7.0_75-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.75-b04, mixed mode)

Interestingly, if I restart the app I immediately;y get an error:

$ java -Dfile.encoding=UTF-8 -classpath target/classes:/Users/max/.m2/repository/com/innowhere/relproxy/0.8.8/relproxy-0.8.jar com.mycompany.app.App
RelProxy to be enabled, development mode detected
Before compile: /Users/max/src/Playground/jproxy-test/my-app/src/main/java/com/mycompany/app/TestListener.java
After compile: /Users/max/src/Playground/jproxy-test/my-app/src/main/java/com/mycompany/app/TestListener.java
RelProxy running
Reloaded com.mycompany.app.TestListener@5fa0f02a - class com.mycompany.app.TestListener Calling method: public native int java.lang.Object.hashCode() - null
OLD: com.mycompany.app.TestListener@3ef78672 - class com.mycompany.app.TestListener
NEW: com.mycompany.app.TestListener@5fa0f02a - class com.mycompany.app.TestListener
Reloaded com.mycompany.app.TestListener@6c9bc6a9 - class com.mycompany.app.TestListener Calling method: public native int java.lang.Object.hashCode() - null
OLD: com.mycompany.app.TestListener@3ef78672 - class com.mycompany.app.TestListener
NEW: com.mycompany.app.TestListener@6c9bc6a9 - class com.mycompany.app.TestListener
RelProxy stopped
Exception in thread "main" java.lang.RuntimeException: Unexpected Error
    at com.mycompany.app.App.assertTrue(App.java:202)
    at com.mycompany.app.App.mainTest(App.java:182)
    at com.mycompany.app.App.<init>(App.java:41)
    at com.mycompany.app.App.main(App.java:31)
maxott commented 7 years ago

Should have added that mainTest(App.java:182) is:

        assertTrue(rpbRoot.getOutputListenerCount() == 0);
jmarranz commented 7 years ago

Try to replicate the EXACT example code of the manual, then try to modify it progressively, RelProxy is not so sophisticate like JRebel
but it can be very useful (and free) in a object oriented world without state (like in pure functional world)

On 09/10/2016 8:02, Max Ott wrote:

Just tried to recreate the example at the end of the manual and reloading won't work:

|Reloaded com.mycompany.app.TestListener@6a41eaa2 - class com.mycompany.app.TestListener Calling method: public abstract void com.mycompany.app.OutputListener.write(java.io.PrintStream) - [Ljava.lang.Object;@7cd62f43 OLD: com.mycompany.app.TestListener@1e88b3c - class com.mycompany.app.TestListener uppercase lowercase NEW: com.mycompany.app.TestListener@6a41eaa2 - class com.mycompany.app.TestListener java.lang.IllegalArgumentException: object is not an instance of declaring class at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:483) at com.mycompany.app.App$2.onReload(App.java:97) at com.innowhere.relproxy.impl.GenericProxyInvocationHandler.invoke(GenericProxyInvocationHandler.java:40) at com.sun.proxy.$Proxy0.write(Unknown Source) at com.mycompany.app.RelProxyBuiltinImpl.runLoop(RelProxyBuiltinImpl.java:95) at com.mycompany.app.App.mainTest(App.java:191) at com.mycompany.app.App.(App.java:41) at com.mycompany.app.App.main(App.java:31) |

I slightly changed the |RelProxyOnReloadListener| implementation to:

|RelProxyOnReloadListener proxyListener = new RelProxyOnReloadListener() { public void onReload(Object objOld, Object objNew, Object proxy, Method method, Object[] args) { System.out.println("Reloaded " + objNew + " - " + objNew.getClass() + " Calling method: " + method + " - " + args); try { System.out.println("OLD: " + objOld + " - " + objOld.getClass()); method.invoke(objOld, args); System.out.println("NEW: " + objNew + " - " + objNew.getClass()); method.invoke(objNew, args); } catch (Exception e) { e.printStackTrace(); } } }; |

It appears that in my environment, the |Method| object also changes on the recompile.

|$ java -version java version "1.8.0_65" Java(TM) SE Runtime Environment (build 1.8.0_65-b17) Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode) |

Any ideas on how that could be solved? Am I doing something wrong?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/jmarranz/relproxy/issues/7, or mute the thread https://github.com/notifications/unsubscribe-auth/ACwLXE8Rqg5Q4B6W5CIZD_9948LvGT0Hks5qyIOIgaJpZM4KR6sR.