From sari.attila at gravityrd.com Wed Feb 1 09:57:00 2017 From: sari.attila at gravityrd.com (Attila Sari) Date: Wed, 1 Feb 2017 10:57:00 +0100 Subject: raise ecmascript error from JSObject In-Reply-To: <5890C361.3030900@oracle.com> References: <5890C361.3030900@oracle.com> Message-ID: Absolutely, many thanks. On Tue, Jan 31, 2017 at 6:03 PM, Sundararajan Athijegannathan < sundararajan.athijegannathan at oracle.com> wrote: > Hope the following sample code helps you... > > -Sundar > > import javax.script.*; > import jdk.nashorn.api.scripting.*; > > public class Main { > private static JSObject errorCtr; > > public static void main(String[] args) throws Exception { > ScriptEngine e = new ScriptEngineManager().getEngin > eByName("nashorn"); > // save JS Error constructor which is used later to construct Error > object > errorCtr = (JSObject)e.eval("Error"); > e.put("func", new MyFunc()); > e.eval("try { func() } catch(e) { print(e); print(e.stack); } "); > } > > public static class MyFunc extends AbstractJSObject { > public boolean isFunction() { return true; } > > public Object call(Object self, Object... args) { > // this is like "var e = new Error('myErrorMsg')" in JS code > JSObject error = (JSObject)errorCtr.newObject("myErrorMsg"); > // equivalent to "throw e;" > throw (RuntimeException)error.getMember("nashornException"); > > } > } > } > > > On 31/01/17, 10:04 PM, Attila Sari wrote: > >> Hi all, >> >> Is it possible to throw ecmascript error from JSObject methods? (that can >> be catched later in the script, and will be enriched with filename and >> line >> number) >> >> Thanks, >> Attila Sari >> >> -- -- Attila SARI Software developer | Gravity R&D p: +36.1.799.5264 | skype: attila.sari86 | tw: @gravityrd From luisa_pace at it.ibm.com Wed Feb 1 15:09:31 2017 From: luisa_pace at it.ibm.com (Luisa Pace) Date: Wed, 1 Feb 2017 16:09:31 +0100 Subject: nashorn.jar is opensource? In-Reply-To: References: <3002524C-92D3-4161-8070-2BFCC2DF45D1@oracle.com> <588F5956.2050006@oracle.com> Message-ID: Thanks for your details and considerations. I've a question on what you said: Last but not least, the source code at the above URL may or may not contain third party works under different open source licenses. Please check the notices on individual files for details. Is your sentence specific to nashorn or is related to the whole openjdk? Thanks again. Best Regards/Cordiali saluti Luisa Pace ========================================================================================================================= Ci? che ? fuori ? anche dentro; e ci? che non ? dentro non ? da nessuna parte. Per questo viaggiare non serve. Se uno non ha niente dentro, non trover? mai niente fuori. ? inutile andare a cercare nel mondo quel che non si riesce a trovare dentro di s?. (Tiziano Terzani) ========================================================================================================================== Ing. Luisa Pace IBM Italy Bluemix Legal Project Manager Via Sciangai, 53 (B1 - 508) 00144 Roma Italy Tel. +39.06.5966.3795 Fax. +39.06.5966.3489 mob. +39.335.7368629 e-mail: luisa_pace at it.ibm.com From: dalibor topic To: Luisa Pace/Italy/IBM at IBMIT Cc: nashorn-dev at openjdk.java.net Date: 31/01/2017 15.40 Subject: Re: nashorn.jar is opensource? Hi, From your initial query about "To do that, I need of the source of all the CloudFoundry components and their dependencies. In the case I'm managing now, Cloudfoundry (level 245) contains openjdk 1.8.0_101, that in turn contains nashorn.jar." I suspect that your query is really about the corresponding source code for a binary provided by CloudFoundry. Such third party provided binaries may or may not contain additional and/or different source code from the URL below. Please inquire with CloudFoundry directly to get the source code corresponding to the binary you are interested in, if I'm parsing your query correctly. On a more general note, the URL below is for Nashorn source code in JDK 9, rather than for source code of Nashorn in a 1.8.0_* release. The sources of Nashorn in JDK 8 Updates can be found in the Mercurial repository located at http://hg.openjdk.java.net/jdk8u/jdk8u/nashorn/ You can use Mercurial tags to locate source code corresponding to a specific build. Last but not least, the source code at the above URL may or may not contain third party works under different open source licenses. Please check the notices on individual files for details. cheers, dalibor topic On 30.01.2017 16:18, Michel Trudeau wrote: > It's all under http://hg.openjdk.java.net/jdk9/jdk9/nashorn/ > -- Dalibor Topic | Principal Product Manager Phone: +494089091214 | Mobile: +491737185961 ORACLE Deutschland B.V. & Co. KG | K?hneh?fe 5 | 22761 Hamburg ORACLE Deutschland B.V. & Co. KG Hauptverwaltung: Riesstr. 25, D-80992 M?nchen Registergericht: Amtsgericht M?nchen, HRA 95603 Komplement?rin: ORACLE Deutschland Verwaltung B.V. Hertogswetering 163/167, 3543 AS Utrecht, Niederlande Handelsregister der Handelskammer Midden-Niederlande, Nr. 30143697 Gesch?ftsf?hrer: Alexander van der Ven, Jan Schultheiss, Val Maher Oracle is committed to developing practices and products that help protect the environment IBM Italia S.p.A. Sede Legale: Circonvallazione Idroscalo - 20090 Segrate (MI) Cap. Soc. euro 347.256.998,80 C. F. e Reg. Imprese MI 01442240030 - Partita IVA 10914660153 Societ? con unico azionista Societ? soggetta all?attivit? di direzione e coordinamento di International Business Machines Corporation (Salvo che sia diversamente indicato sopra / Unless stated otherwise above) From Joerg.Frantzius at aperto.com Thu Feb 2 15:28:29 2017 From: Joerg.Frantzius at aperto.com (=?utf-8?B?RnJhbnR6aXVzLCBKw7ZyZw==?=) Date: Thu, 2 Feb 2017 15:28:29 +0000 Subject: Map should support hasOwnProperty? Message-ID: <789D3EBD-C996-4536-A259-3719F0581401@aperto.com> Hi, Nashorn?s extensions let Java Map objects behave somewhat like Javascript objects by making its key-values accessible as object properties. Unfortunately, it seems that hasOwnProperty() is commonly used in Javascript code to iterate the properties of an object, and this doesn?t work on Map objects. Maybe it would be a good idea to also support hasOwnProperty() on Map objects? Currently it seems impossible to let 3d party Javascript code traverse a a Java object graph with nested Map objects. While I may be able to traverse and convert a Java object graph if it is made from Collections, Arrays and Maps, this will fail as soon as there is a custom Java class involved that has a Map field (that is accessed from Javascript). Thanks for any thoughts, J?rg --- Dipl. Inf. J?rg von Frantzius, Technical Director E-Mail joerg.frantzius at aperto.com Phone +49 30 283921-318 Fax +49 30 283921-29 Aperto GmbH ? An IBM Company Chausseestra?e 5, D-10115 Berlin http://www.aperto.com http://www.facebook.com/aperto https://www.xing.com/companies/apertoag HRB 77049 B, AG Berlin Charlottenburg Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel Simon From hannes.wallnoefer at oracle.com Thu Feb 2 17:20:45 2017 From: hannes.wallnoefer at oracle.com (=?utf-8?Q?Hannes_Walln=C3=B6fer?=) Date: Thu, 2 Feb 2017 18:20:45 +0100 Subject: Map should support hasOwnProperty? In-Reply-To: <789D3EBD-C996-4536-A259-3719F0581401@aperto.com> References: <789D3EBD-C996-4536-A259-3719F0581401@aperto.com> Message-ID: <1E5C722D-16D0-4BFE-9242-CAB318918259@oracle.com> Hi J?rg, We have currently no plans to make Object.prototype.hasOwnProperty on non-JavaScript objects. However, I recently pushed a change that makes the in-operator work with Java objects, maps, lists, and arrays to JDK 9. https://bugs.openjdk.java.net/browse/JDK-8173480 Hannes > Am 02.02.2017 um 16:28 schrieb Frantzius, J?rg : > > Hi, > > Nashorn?s extensions let Java Map objects behave somewhat like Javascript objects by making its key-values accessible as object properties. > > Unfortunately, it seems that hasOwnProperty() is commonly used in Javascript code to iterate the properties of an object, and this doesn?t work on Map objects. Maybe it would be a good idea to also support hasOwnProperty() on Map objects? > > Currently it seems impossible to let 3d party Javascript code traverse a a Java object graph with nested Map objects. While I may be able to traverse and convert a Java object graph if it is made from Collections, Arrays and Maps, this will fail as soon as there is a custom Java class involved that has a Map field (that is accessed from Javascript). > > Thanks for any thoughts, > J?rg > > > --- > > Dipl. Inf. J?rg von Frantzius, Technical Director > > E-Mail joerg.frantzius at aperto.com > > Phone +49 30 283921-318 > Fax +49 30 283921-29 > > Aperto GmbH ? An IBM Company > Chausseestra?e 5, D-10115 Berlin > http://www.aperto.com > http://www.facebook.com/aperto > https://www.xing.com/companies/apertoag > > HRB 77049 B, AG Berlin Charlottenburg > Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel Simon > From hannes.wallnoefer at oracle.com Fri Feb 3 08:58:36 2017 From: hannes.wallnoefer at oracle.com (=?utf-8?Q?Hannes_Walln=C3=B6fer?=) Date: Fri, 3 Feb 2017 09:58:36 +0100 Subject: JDK 9 RFR of JDK-8173864: Problem list src/jdk/nashorn/api/tree/test/ParseAPITest.java for some platforms In-Reply-To: <5894460B.40802@oracle.com> References: <3e4187f1-a09d-168a-8047-be4b7ae1efdb@oracle.com> <5894460B.40802@oracle.com> Message-ID: <7E1341AA-616C-450D-8475-D3D6C85BDBFD@oracle.com> +1 Hannes > Am 03.02.2017 um 09:57 schrieb Sundararajan Athijegannathan : > > +1 > > -Sundar > > On 03/02/17, 10:24 AM, Amy Lu wrote: >> src/jdk/nashorn/api/tree/test/ParseAPITest.java >> >> This nashorn test keeps failing at linux-i586, windows-i586 and solaris-sparcv9 (JDK-8173863) >> >> Please review this patch to put the test to problem list until issues addressed. >> >> bug: https://bugs.openjdk.java.net/browse/JDK-8173864 >> webrev: http://cr.openjdk.java.net/~amlu/8173864/webrev.00/ >> >> Thanks, >> Amy >> >> >> --- old/test/ProblemList.txt 2017-02-03 12:45:00.000000000 +0800 >> +++ new/test/ProblemList.txt 2017-02-03 12:44:59.000000000 +0800 >> @@ -23,4 +23,4 @@ >> # >> ########################################################################### >> >> -# No nashorn tests are on the problem list. >> +src/jdk/nashorn/api/tree/test/ParseAPITest.java 8173863 linux-i586,windows-i586,solaris-sparcv9 >> From hannes.wallnoefer at oracle.com Fri Feb 3 11:37:51 2017 From: hannes.wallnoefer at oracle.com (=?utf-8?Q?Hannes_Walln=C3=B6fer?=) Date: Fri, 3 Feb 2017 12:37:51 +0100 Subject: RFR: 8173888: Test for JDK-8169481 causes stack overflows in parser tests Message-ID: Please review: Bug: https://bugs.openjdk.java.net/browse/JDK-8173888 Webrev: http://cr.openjdk.java.net/~hannesw/8173888/webrev.00/ Note that the bug that introduced the problematic test is confidential, the changeset contained adjustments to the splitter weight calculation: http://hg.openjdk.java.net/jdk9/dev/nashorn/rev/ea1d4ecf5862 Thanks, Hannes From james.laskey at oracle.com Fri Feb 3 12:09:43 2017 From: james.laskey at oracle.com (Jim Laskey (Oracle)) Date: Fri, 3 Feb 2017 08:09:43 -0400 Subject: RFR: 8173888: Test for JDK-8169481 causes stack overflows in parser tests In-Reply-To: References: Message-ID: <2FE977D5-5F57-4FFE-A018-2DAA50804DD6@oracle.com> +1 > On Feb 3, 2017, at 7:37 AM, Hannes Walln?fer wrote: > > Please review: > > Bug: https://bugs.openjdk.java.net/browse/JDK-8173888 > Webrev: http://cr.openjdk.java.net/~hannesw/8173888/webrev.00/ > > Note that the bug that introduced the problematic test is confidential, the changeset contained adjustments to the splitter weight calculation: > > http://hg.openjdk.java.net/jdk9/dev/nashorn/rev/ea1d4ecf5862 > > Thanks, > Hannes From sundararajan.athijegannathan at oracle.com Fri Feb 3 12:39:31 2017 From: sundararajan.athijegannathan at oracle.com (Sundararajan Athijegannathan) Date: Fri, 03 Feb 2017 18:09:31 +0530 Subject: RFR: 8173888: Test for JDK-8169481 causes stack overflows in parser tests In-Reply-To: References: Message-ID: <58947A03.40500@oracle.com> +1 On 03/02/17, 5:07 PM, Hannes Walln?fer wrote: > Please review: > > Bug: https://bugs.openjdk.java.net/browse/JDK-8173888 > Webrev: http://cr.openjdk.java.net/~hannesw/8173888/webrev.00/ > > Note that the bug that introduced the problematic test is confidential, the changeset contained adjustments to the splitter weight calculation: > > http://hg.openjdk.java.net/jdk9/dev/nashorn/rev/ea1d4ecf5862 > > Thanks, > Hannes From amy.lu at oracle.com Fri Feb 3 04:54:07 2017 From: amy.lu at oracle.com (Amy Lu) Date: Fri, 3 Feb 2017 12:54:07 +0800 Subject: JDK 9 RFR of JDK-8173864: Problem list src/jdk/nashorn/api/tree/test/ParseAPITest.java for some platforms Message-ID: <3e4187f1-a09d-168a-8047-be4b7ae1efdb@oracle.com> src/jdk/nashorn/api/tree/test/ParseAPITest.java This nashorn test keeps failing at linux-i586, windows-i586 and solaris-sparcv9 (JDK-8173863) Please review this patch to put the test to problem list until issues addressed. bug: https://bugs.openjdk.java.net/browse/JDK-8173864 webrev: http://cr.openjdk.java.net/~amlu/8173864/webrev.00/ Thanks, Amy --- old/test/ProblemList.txt 2017-02-03 12:45:00.000000000 +0800 +++ new/test/ProblemList.txt 2017-02-03 12:44:59.000000000 +0800 @@ -23,4 +23,4 @@ # ########################################################################### -# No nashorn tests are on the problem list. +src/jdk/nashorn/api/tree/test/ParseAPITest.java 8173863 linux-i586,windows-i586,solaris-sparcv9 From huaming.li at oracle.com Fri Feb 10 03:43:17 2017 From: huaming.li at oracle.com (Hamlin Li) Date: Fri, 10 Feb 2017 11:43:17 +0800 Subject: RFR of JDK-8174699: Fix @since in module-info.java in dev/nashorn repo Message-ID: Would you please review the below patch? bug: https://bugs.openjdk.java.net/browse/JDK-8174699 webrev: http://cr.openjdk.java.net/~mli/8174699/webrev.00/ Thank you -Hamlin From james.laskey at oracle.com Fri Feb 10 12:20:15 2017 From: james.laskey at oracle.com (Jim Laskey (Oracle)) Date: Fri, 10 Feb 2017 08:20:15 -0400 Subject: RFR of JDK-8174699: Fix @since in module-info.java in dev/nashorn repo In-Reply-To: References: Message-ID: <1D93CB26-A4A9-458C-B64D-757D7F5FA35B@oracle.com> +1 Go ahead and push. > On Feb 9, 2017, at 11:43 PM, Hamlin Li wrote: > > Would you please review the below patch? > > bug: https://bugs.openjdk.java.net/browse/JDK-8174699 > > webrev: http://cr.openjdk.java.net/~mli/8174699/webrev.00/ > > > Thank you > > -Hamlin > From tomas at tzima.cz Sun Feb 12 06:26:51 2017 From: tomas at tzima.cz (=?UTF-8?B?VG9tw6HFoSBaw61tYQ==?=) Date: Sun, 12 Feb 2017 07:26:51 +0100 Subject: Memory overhead of having too many contexts Message-ID: <58A0002B.50802@tzima.cz> Hello. For one project, I need to be able to evaluate a lot of scripts independently. However, after implementing a solution where each script uses a different ScriptContext, I found out there's a huge memory overhead. I reproduced it in the following code: NashornScriptEngine engine = (NashornScriptEngine) new NashornScriptEngineFactory().getScriptEngine(); CompiledScript compiledFunction = engine.compile("function f() {}"); List contexts = new ArrayList<>(); for (int i = 0; i < 10_000; i++) { SimpleScriptContext context = new SimpleScriptContext(); context.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE); compiledFunction.eval(context); contexts.add(context); } System.gc(); MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); System.out.printf("Heap: %,12d B\n", memoryMXBean.getHeapMemoryUsage().getUsed()); System.out.printf("Non-Heap: %,12d B\n", memoryMXBean.getNonHeapMemoryUsage().getUsed()); Thread.sleep(Long.MAX_VALUE); Running on my machine with OpenJDK 1.8.0_111, it prints the following: Heap: 1,093,960,464 B Non-Heap: 22,980,864 B I looked into the heap dump in VisualVM and found out, to my surprise, that there are about 2.2 million instances of jdk.nashorn.internal.runtime.CompiledFunction. These instances occupy 11 % of heap in size. There's also 1.3 million instances of jdk.nashorn.internal.runtime.ScriptFunction (9 % of heap in size). It scales with the amount of contexts. For example, when I create only 1000 contexts, there's about 1/10th of instances. Why is there so many? I wonder if creating a new context doesn't result in recompiling/reinterpreting/redefining all standard functions which are normally present in global namespace. That could be an answer for why there's about ~350 functions (either CompiledFunction or ScriptFunction) per context. Obviously, this is just a guess since I don't know much about how Nashorn works internally. Note: When using Bindings instead of ScriptContext, it ends up using about twice as small heap but creates the same amount of instances of CompiledFunction and ScriptFunction. What can I do to prevent such tremendous memory costs? We previously used Rhino with the same amount of independent contexts and it certainly had much smaller memory footprint. Thanks. -- tzima From Joerg.Frantzius at aperto.com Sat Feb 18 23:47:25 2017 From: Joerg.Frantzius at aperto.com (=?utf-8?B?RnJhbnR6aXVzLCBKw7ZyZw==?=) Date: Sat, 18 Feb 2017 23:47:25 +0000 Subject: Closures not thread-safe? Message-ID: <176720BC-74CA-4C83-96E2-5F2A6BFFC6BB@aperto.com> Hi, it begins to dawn on me that closures aren?t thread-safe, at least that would explain crosstalk issues we?re seeing in JMeter tests (with a single engine for multiple threads). It would be good to know (and I guess for others as well) if somebody can confirm this? Perhaps thread-safety of closures was thinkable if Nashorn somehow stored closure state in ThreadLocals, but I guess that?s neither happening nor planned? From what I understand, closures are pervasive in Javascript code out there, and anybody using such code will currently be forced to use engine-per-thread. Thanks for any hints, J?rg --- Dipl. Inf. J?rg von Frantzius, Technical Director E-Mail joerg.frantzius at aperto.com Phone +49 30 283921-318 Fax +49 30 283921-29 Aperto GmbH ? An IBM Company Chausseestra?e 5, D-10115 Berlin http://www.aperto.com http://www.facebook.com/aperto https://www.xing.com/companies/apertoag HRB 77049 B, AG Berlin Charlottenburg Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel Simon From Joerg.Frantzius at aperto.com Sun Feb 19 21:30:44 2017 From: Joerg.Frantzius at aperto.com (=?utf-8?B?RnJhbnR6aXVzLCBKw7ZyZw==?=) Date: Sun, 19 Feb 2017 21:30:44 +0000 Subject: Closures not thread-safe? In-Reply-To: <176720BC-74CA-4C83-96E2-5F2A6BFFC6BB@aperto.com> References: <176720BC-74CA-4C83-96E2-5F2A6BFFC6BB@aperto.com> Message-ID: <562C5C98-48CB-40CD-9C2F-7344E8015208@aperto.com> ? to correct myself, with code that contains closures, it?s probably global-per-thread on a single engine that remains as the least resource-consuming option (we were using a single global on single engine for all threads, in order to share expensively computed Javascript state between them). From what I understand, global-per-thread could be implemented e.g. by having a ThreadLocal and always using that as the context in ScriptEngine.eval(script, context). It would be good to know then whether global-per-thread on single engine still allows for sharing Nashorn?s code optimization between threads? That would already be great (and as Nashorn *is* great, I?m positive here :) Regards, J?rg Am 19.02.2017 um 00:47 schrieb Frantzius, J?rg >: Hi, it begins to dawn on me that closures aren?t thread-safe, at least that would explain crosstalk issues we?re seeing in JMeter tests (with a single engine for multiple threads). It would be good to know (and I guess for others as well) if somebody can confirm this? Perhaps thread-safety of closures was thinkable if Nashorn somehow stored closure state in ThreadLocals, but I guess that?s neither happening nor planned? From what I understand, closures are pervasive in Javascript code out there, and anybody using such code will currently be forced to use engine-per-thread. Thanks for any hints, J?rg --- Dipl. Inf. J?rg von Frantzius, Technical Director E-Mail joerg.frantzius at aperto.com Phone +49 30 283921-318 Fax +49 30 283921-29 Aperto GmbH ? An IBM Company Chausseestra?e 5, D-10115 Berlin http://www.aperto.com http://www.facebook.com/aperto https://www.xing.com/companies/apertoag HRB 77049 B, AG Berlin Charlottenburg Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel Simon --- Dipl. Inf. J?rg von Frantzius, Technical Director E-Mail joerg.frantzius at aperto.com Phone +49 30 283921-318 Fax +49 30 283921-29 Aperto GmbH ? An IBM Company Chausseestra?e 5, D-10115 Berlin http://www.aperto.com http://www.facebook.com/aperto https://www.xing.com/companies/apertoag HRB 77049 B, AG Berlin Charlottenburg Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel Simon From joaovarandas at inpaas.com Mon Feb 20 12:00:17 2017 From: joaovarandas at inpaas.com (=?UTF-8?Q?Jo=C3=A3o_Paulo_Varandas?=) Date: Mon, 20 Feb 2017 09:00:17 -0300 Subject: Closures not thread-safe? In-Reply-To: <562C5C98-48CB-40CD-9C2F-7344E8015208@aperto.com> References: <176720BC-74CA-4C83-96E2-5F2A6BFFC6BB@aperto.com> <562C5C98-48CB-40CD-9C2F-7344E8015208@aperto.com> Message-ID: Hi Jorg. Could you send us a code snippet? I have never seem such problem when using closures. In my project, I use a single engine for whole web application. My tomcat is running with 150 maxThreads and it seems to be working fine. I test that in each build by running the test case below: https://gist.github.com/joaovarandas/f80a9cb5548a9d620e4da1ace2729911 The idea in this test is to use a single engine and run a closure from one-thread or multiple-threads simultaneously and then read data from those closures. PS.: Should I send the source code directly in the mail body for future readers? Jo?o Varandas *Arquiteto de Solu??es Cloud* inPaaS - Id?ias em Aplica??es p: +55 11 5091-2777 m: +55 11 99889-2321 a: Rua Nebraska, 443 - 1o Andar Brooklin Paulista, S?o Paulo, SP w: www.inpaas.com e: joaovarandas at inpaas.com 2017-02-19 18:30 GMT-03:00 Frantzius, J?rg : > ? to correct myself, with code that contains closures, it?s probably > global-per-thread on a single engine that remains as the least > resource-consuming option (we were using a single global on single engine > for all threads, in order to share expensively computed Javascript state > between them). > > From what I understand, global-per-thread could be implemented e.g. by > having a ThreadLocal and always using that as the context in > ScriptEngine.eval(script, context). > > It would be good to know then whether global-per-thread on single engine > still allows for sharing Nashorn?s code optimization between threads? That > would already be great (and as Nashorn *is* great, I?m positive here :) > > Regards, > J?rg > > > Am 19.02.2017 um 00:47 schrieb Frantzius, J?rg >: > > Hi, > > it begins to dawn on me that closures aren?t thread-safe, at least that > would explain crosstalk issues we?re seeing in JMeter tests (with a single > engine for multiple threads). > > It would be good to know (and I guess for others as well) if somebody can > confirm this? > > Perhaps thread-safety of closures was thinkable if Nashorn somehow stored > closure state in ThreadLocals, but I guess that?s neither happening nor > planned? > > From what I understand, closures are pervasive in Javascript code out > there, and anybody using such code will currently be forced to use > engine-per-thread. > > Thanks for any hints, > J?rg > > > --- > > Dipl. Inf. J?rg von Frantzius, Technical Director > > E-Mail joerg.frantzius at aperto.com > > Phone +49 30 283921-318 > Fax +49 30 283921-29 > > Aperto GmbH ? An IBM Company > Chausseestra?e 5, D-10115 Berlin > http://www.aperto.com > http://www.facebook.com/aperto > https://www.xing.com/companies/apertoag > > HRB 77049 B, AG Berlin Charlottenburg > Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel > Simon > > > > --- > > Dipl. Inf. J?rg von Frantzius, Technical Director > > E-Mail joerg.frantzius at aperto.com > > Phone +49 30 283921-318 > Fax +49 30 283921-29 > > Aperto GmbH ? An IBM Company > Chausseestra?e 5, D-10115 Berlin > http://www.aperto.com > http://www.facebook.com/aperto > https://www.xing.com/companies/apertoag > > HRB 77049 B, AG Berlin Charlottenburg > Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel > Simon > > -- "Esta mensagem, incluindo seus anexos, pode conter informacoes confidenciais e privilegiadas. Se voce a recebeu por engano, solicitamos que a apague e avise o remetente imediatamente. Opinioes ou informacoes aqui contidas nao refletem necessariamente a posicao oficial da Plusoft." "Antes de imprimir, pense em sua responsabilidade e compromisso com o MEIO AMBIENTE" From Joerg.Frantzius at aperto.com Mon Feb 20 13:32:33 2017 From: Joerg.Frantzius at aperto.com (=?utf-8?B?RnJhbnR6aXVzLCBKw7ZyZw==?=) Date: Mon, 20 Feb 2017 13:32:33 +0000 Subject: Closures not thread-safe? In-Reply-To: References: <176720BC-74CA-4C83-96E2-5F2A6BFFC6BB@aperto.com> <562C5C98-48CB-40CD-9C2F-7344E8015208@aperto.com> Message-ID: Hi Joao, the following test fails immediately for me with "java.lang.RuntimeException: Expected: Thread[ForkJoinPool.commonPool-worker-4,5,main], received: Thread[main,5,main]": @Test public void testClosureThreadSafety() throws ScriptException { final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); String testJsFunction = ( " (function outerFunction(currentThreadName) {\n" + " function innerFunction() {\n" + " return currentThreadName;\n" + " }\n" + " return innerFunction;\n" + " })(java.lang.Thread.currentThread().toString())\n"); ScriptObjectMirror jsFunction = (ScriptObjectMirror) engine.eval(testJsFunction); IntConsumer invokeAndTest = i-> { String currentThreadName = Thread.currentThread().toString(); Object received = jsFunction.call(jsFunction); if (!currentThreadName.equals(received)) { throw new RuntimeException("Expected: " + currentThreadName + ", received: " + received); } }; IntStream.range(0, 10).parallel().forEach(invokeAndTest); } The outer function returns its inner function, which contains ?currentThread? as a reference to its closure (i.e. a reference to outerFunction?s ?currentThread? parameter). That closure property ?currentThread? will be set to the name of the current thread only once (in engine.eval(testJsFunction)), and subsequent calls to innerFunction will always return the name of that thread (and not of the current thread that calls innerFunction). If your Javascript code is under your control, this may not be a problem, as you can change the code. In our case, we are using an existing Javascript library ?Handlebars? that we cannot change, which seems to be keeping function objects with closures around just like the above code does in Java. Regards, J?rg Am 20.02.2017 um 13:00 schrieb Jo?o Paulo Varandas >: Hi Jorg. Could you send us a code snippet? I have never seem such problem when using closures. In my project, I use a single engine for whole web application. My tomcat is running with 150 maxThreads and it seems to be working fine. I test that in each build by running the test case below: https://gist.github.com/joaovarandas/f80a9cb5548a9d620e4da1ace2729911 The idea in this test is to use a single engine and run a closure from one-thread or multiple-threads simultaneously and then read data from those closures. PS.: Should I send the source code directly in the mail body for future readers? [https://static.inpaas.com/assets/inpaas/images/logo-img-50px.png] Jo?o Varandas Arquiteto de Solu??es Cloud inPaaS - Id?ias em Aplica??es p: +55 11 5091-2777 m: +55 11 99889-2321 a: Rua Nebraska, 443 - 1o Andar Brooklin Paulista, S?o Paulo, SP w: www.inpaas.com e: joaovarandas at inpaas.com 2017-02-19 18:30 GMT-03:00 Frantzius, J?rg >: ? to correct myself, with code that contains closures, it?s probably global-per-thread on a single engine that remains as the least resource-consuming option (we were using a single global on single engine for all threads, in order to share expensively computed Javascript state between them). From what I understand, global-per-thread could be implemented e.g. by having a ThreadLocal and always using that as the context in ScriptEngine.eval(script, context). It would be good to know then whether global-per-thread on single engine still allows for sharing Nashorn?s code optimization between threads? That would already be great (and as Nashorn *is* great, I?m positive here :) Regards, J?rg Am 19.02.2017 um 00:47 schrieb Frantzius, J?rg >>: Hi, it begins to dawn on me that closures aren?t thread-safe, at least that would explain crosstalk issues we?re seeing in JMeter tests (with a single engine for multiple threads). It would be good to know (and I guess for others as well) if somebody can confirm this? Perhaps thread-safety of closures was thinkable if Nashorn somehow stored closure state in ThreadLocals, but I guess that?s neither happening nor planned? From what I understand, closures are pervasive in Javascript code out there, and anybody using such code will currently be forced to use engine-per-thread. Thanks for any hints, J?rg --- Dipl. Inf. J?rg von Frantzius, Technical Director E-Mail joerg.frantzius at aperto.com> Phone +49 30 283921-318 Fax +49 30 283921-29 Aperto GmbH ? An IBM Company Chausseestra?e 5, D-10115 Berlin http://www.aperto.com http://www.facebook.com/aperto https://www.xing.com/companies/apertoag HRB 77049 B, AG Berlin Charlottenburg Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel Simon --- Dipl. Inf. J?rg von Frantzius, Technical Director E-Mail joerg.frantzius at aperto.com Phone +49 30 283921-318 Fax +49 30 283921-29 Aperto GmbH ? An IBM Company Chausseestra?e 5, D-10115 Berlin http://www.aperto.com http://www.facebook.com/aperto https://www.xing.com/companies/apertoag HRB 77049 B, AG Berlin Charlottenburg Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel Simon "Esta mensagem, incluindo seus anexos, pode conter informacoes confidenciais e privilegiadas. Se voce a recebeu por engano, solicitamos que a apague e avise o remetente imediatamente. Opinioes ou informacoes aqui contidas nao refletem necessariamente a posicao oficial da Plusoft." "Antes de imprimir, pense em sua responsabilidade e compromisso com o MEIO AMBIENTE" --- Dipl. Inf. J?rg von Frantzius, Technical Director E-Mail joerg.frantzius at aperto.com Phone +49 30 283921-318 Fax +49 30 283921-29 Aperto GmbH ? An IBM Company Chausseestra?e 5, D-10115 Berlin http://www.aperto.com http://www.facebook.com/aperto https://www.xing.com/companies/apertoag HRB 77049 B, AG Berlin Charlottenburg Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel Simon From joaovarandas at inpaas.com Mon Feb 20 13:50:10 2017 From: joaovarandas at inpaas.com (=?UTF-8?Q?Jo=C3=A3o_Paulo_Varandas?=) Date: Mon, 20 Feb 2017 10:50:10 -0300 Subject: Closures not thread-safe? In-Reply-To: References: <176720BC-74CA-4C83-96E2-5F2A6BFFC6BB@aperto.com> <562C5C98-48CB-40CD-9C2F-7344E8015208@aperto.com> Message-ID: There is no issue there. When your code is evaluated, currentThreadName is not a pointer to current thread name. It is a string, that has been evaluated only once. It won't change in different executions, remaining as "main" despite the executing thread(the closure has been created and it's variables are safely stored inside the closure). Check out the changes in the code: @Test public void testClosureThreadSafety() throws ScriptException { String testJsFunction = ( " (function outerFunction(currentThreadName) {\n" + " function innerFunction() {\n" + " print(currentThreadName, java.lang.Thread.currentThread().toString()); return currentThreadName;\n" + " }\n" + " return innerFunction;\n" + " })(java.lang.Thread.currentThread().toString())\n"); ScriptObjectMirror jsFunction = (ScriptObjectMirror) e.eval(testJsFunction); String currentThreadName = Thread.currentThread().toString(); IntConsumer invokeAndTest = i-> { Object received = jsFunction.call(jsFunction); Assert.assertEquals(currentThreadName, received); }; IntStream.range(0, 10).parallel().forEach(invokeAndTest); } I've added a "print(currentThreadName, java.lang.Thread.currentThread().toString()); " to prove that currentThreadName stays the same in all executions despite which Thread it is executing. Check out this one now: @Test public void testClosureThreadSafety2() throws ScriptException { String testJsFunction = ( " (function outerFunction(threadPointer) {\n" + " function innerFunction() {\n" + " return threadPointer().toString();\n" + " }\n" + " return innerFunction;\n" + " })(java.lang.Thread.currentThread)\n"); ScriptObjectMirror jsFunction = (ScriptObjectMirror) e.eval(testJsFunction); IntConsumer invokeAndTest = i-> { Object received = jsFunction.call(jsFunction); Assert.assertEquals(Thread.currentThread().toString(), received); }; IntStream.range(0, 10).parallel().forEach(invokeAndTest); } Now there's a pointer to currentThread(not a string), and you can use it in every thread returning different data. Jo?o Varandas *Arquiteto de Solu??es Cloud* inPaaS - Id?ias em Aplica??es p: +55 11 5091-2777 m: +55 11 99889-2321 a: Rua Nebraska, 443 - 1o Andar Brooklin Paulista, S?o Paulo, SP w: www.inpaas.com e: joaovarandas at inpaas.com 2017-02-20 10:32 GMT-03:00 Frantzius, J?rg : > Hi Joao, > > the following test fails immediately for me with > "java.lang.RuntimeException: Expected: Thread[ForkJoinPool.commonPool-worker-4,5,main], > received: Thread[main,5,main]": > > @Test > public void testClosureThreadSafety() throws ScriptException { > final ScriptEngine engine = new ScriptEngineManager(). > getEngineByName("nashorn"); > > String testJsFunction = ( > " (function outerFunction(currentThreadName) {\n" + > " function innerFunction() {\n" + > " return currentThreadName;\n" + > " }\n" + > " return innerFunction;\n" + > " })(java.lang.Thread.currentThread().toString())\n"); > > ScriptObjectMirror jsFunction = (ScriptObjectMirror) engine.eval( > testJsFunction); > > IntConsumer invokeAndTest = i-> { > String currentThreadName = Thread.currentThread().toString(); > Object received = jsFunction.call(jsFunction); > if (!currentThreadName.equals(received)) { > throw new RuntimeException("Expected: " + > currentThreadName + ", received: " + received); > } > }; > IntStream.range(0, 10).parallel().forEach(invokeAndTest); > } > > The outer function returns its inner function, which contains > ?currentThread? as a reference to its closure (i.e. a reference to > outerFunction?s ?currentThread? parameter). That closure property > ?currentThread? will be set to the name of the current thread only once (in > engine.eval(testJsFunction)), and subsequent calls to innerFunction will > always return the name of that thread (and not of the current thread that > calls innerFunction). > > If your Javascript code is under your control, this may not be a problem, > as you can change the code. In our case, we are using an existing > Javascript library ?Handlebars? that we cannot change, which seems to be > keeping function objects with closures around just like the above code does > in Java. > > Regards, > J?rg > > Am 20.02.2017 um 13:00 schrieb Jo?o Paulo Varandas < > joaovarandas at inpaas.com>: > > Hi Jorg. > > Could you send us a code snippet? > > I have never seem such problem when using closures. In my project, I use a > single engine for whole web application. My tomcat is running with 150 > maxThreads and it seems to be working fine. I test that in each build by > running the test case below: > > https://gist.github.com/joaovarandas/f80a9cb5548a9d620e4da1ace2729911 > > The idea in this test is to use a single engine and run a closure from > one-thread or multiple-threads simultaneously and then read data from those > closures. > > > PS.: Should I send the source code directly in the mail body for future > readers? > > > > > > Jo?o Varandas > *Arquiteto de Solu??es Cloud* > inPaaS - Id?ias em Aplica??es > > p: +55 11 5091-2777 <+55%2011%205091-2777> m: +55 11 99889-2321 > <+55%2011%2099889-2321> > a: Rua Nebraska, 443 - 1o Andar > Brooklin Paulista, S?o Paulo, SP > w: www.inpaas.com e: joaovarandas at inpaas.com > > > 2017-02-19 18:30 GMT-03:00 Frantzius, J?rg : > >> ? to correct myself, with code that contains closures, it?s probably >> global-per-thread on a single engine that remains as the least >> resource-consuming option (we were using a single global on single engine >> for all threads, in order to share expensively computed Javascript state >> between them). >> >> From what I understand, global-per-thread could be implemented e.g. by >> having a ThreadLocal and always using that as the context in >> ScriptEngine.eval(script, context). >> >> It would be good to know then whether global-per-thread on single engine >> still allows for sharing Nashorn?s code optimization between threads? That >> would already be great (and as Nashorn *is* great, I?m positive here :) >> >> Regards, >> J?rg >> >> >> Am 19.02.2017 um 00:47 schrieb Frantzius, J?rg < >> Joerg.Frantzius at aperto.com>: >> >> Hi, >> >> it begins to dawn on me that closures aren?t thread-safe, at least that >> would explain crosstalk issues we?re seeing in JMeter tests (with a single >> engine for multiple threads). >> >> It would be good to know (and I guess for others as well) if somebody can >> confirm this? >> >> Perhaps thread-safety of closures was thinkable if Nashorn somehow stored >> closure state in ThreadLocals, but I guess that?s neither happening nor >> planned? >> >> From what I understand, closures are pervasive in Javascript code out >> there, and anybody using such code will currently be forced to use >> engine-per-thread. >> >> Thanks for any hints, >> J?rg >> >> >> --- >> >> Dipl. Inf. J?rg von Frantzius, Technical Director >> >> E-Mail joerg.frantzius at aperto.com >> >> Phone +49 30 283921-318 >> Fax +49 30 283921-29 >> >> Aperto GmbH ? An IBM Company >> Chausseestra?e 5, D-10115 Berlin >> http://www.aperto.com >> http://www.facebook.com/aperto >> https://www.xing.com/companies/apertoag >> >> HRB 77049 B, AG Berlin Charlottenburg >> Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel >> Simon >> >> >> >> --- >> >> Dipl. Inf. J?rg von Frantzius, Technical Director >> >> E-Mail joerg.frantzius at aperto.com >> >> Phone +49 30 283921-318 >> Fax +49 30 283921-29 >> >> Aperto GmbH ? An IBM Company >> Chausseestra?e 5, D-10115 Berlin >> http://www.aperto.com >> http://www.facebook.com/aperto >> https://www.xing.com/companies/apertoag >> >> HRB 77049 B, AG Berlin Charlottenburg >> Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel >> Simon >> >> > > "Esta mensagem, incluindo seus anexos, pode conter informacoes > confidenciais e privilegiadas. > Se voce a recebeu por engano, solicitamos que a apague e avise o remetente > imediatamente. > Opinioes ou informacoes aqui contidas nao refletem necessariamente a > posicao oficial da Plusoft." > > "Antes de imprimir, pense em sua responsabilidade e compromisso com o MEIO > AMBIENTE" > > > *---* > > *Dipl. Inf. J?rg von Frantzius, Technical Director* > > E-Mail joerg.frantzius at aperto.com > > Phone +49 30 283921-318 <+49%2030%20283921318> > Fax +49 30 283921-29 <+49%2030%2028392129> > > Aperto GmbH ? An IBM Company > Chausseestra?e 5, D-10115 Berlin > http://www.aperto.com > http://www.facebook.com/aperto > https://www.xing.com/companies/apertoag > > HRB 77049 B, AG Berlin Charlottenburg > Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel > Simon > > -- "Esta mensagem, incluindo seus anexos, pode conter informacoes confidenciais e privilegiadas. Se voce a recebeu por engano, solicitamos que a apague e avise o remetente imediatamente. Opinioes ou informacoes aqui contidas nao refletem necessariamente a posicao oficial da Plusoft." "Antes de imprimir, pense em sua responsabilidade e compromisso com o MEIO AMBIENTE" From joaovarandas at inpaas.com Mon Feb 20 14:35:12 2017 From: joaovarandas at inpaas.com (=?UTF-8?Q?Jo=C3=A3o_Paulo_Varandas?=) Date: Mon, 20 Feb 2017 11:35:12 -0300 Subject: Closures not thread-safe? In-Reply-To: References: <176720BC-74CA-4C83-96E2-5F2A6BFFC6BB@aperto.com> <562C5C98-48CB-40CD-9C2F-7344E8015208@aperto.com> Message-ID: A JS closure is just like a POJO. If you share a POJO between threads, values are the same for all threads, if you need threads to have their own values, you need a new POJO for each thread. Just like POJO instances, closures are "independent", you may have N instances of a specific closure in the same engine and they may have different values inside. Refering to MDN docs: Closures are functions that refer to independent (free) variables. In other words, the function defined in the closure ?remembers? the environment in which it was created. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures -- So it seems to me that Nashorn handles closures perfectly, the problem is that most javascript libraries are not thread-safe, by the way, maybe your issue is that wycat's handlebars is not thread safe... Jo?o Varandas *Arquiteto de Solu??es Cloud* inPaaS - Id?ias em Aplica??es p: +55 11 5091-2777 m: +55 11 99889-2321 a: Rua Nebraska, 443 - 1o Andar Brooklin Paulista, S?o Paulo, SP w: www.inpaas.com e: joaovarandas at inpaas.com 2017-02-20 10:50 GMT-03:00 Jo?o Paulo Varandas : > There is no issue there. > When your code is evaluated, currentThreadName is not a pointer to current > thread name. It is a string, that has been evaluated only once. > > It won't change in different executions, remaining as "main" despite the > executing thread(the closure has been created and it's variables are safely > stored inside the closure). > > Check out the changes in the code: > > @Test > public void testClosureThreadSafety() throws ScriptException { > String testJsFunction = ( > " (function outerFunction(currentThreadName) {\n" + > " function innerFunction() {\n" + > " print(currentThreadName, java.lang.Thread.currentThread().toString()); > return currentThreadName;\n" + > " }\n" + > " return innerFunction;\n" + > " })(java.lang.Thread.currentThread().toString())\n"); > > ScriptObjectMirror jsFunction = (ScriptObjectMirror) > e.eval(testJsFunction); > > String currentThreadName = Thread.currentThread().toString(); > > IntConsumer invokeAndTest = i-> { > Object received = jsFunction.call(jsFunction); > > Assert.assertEquals(currentThreadName, received); > }; > IntStream.range(0, 10).parallel().forEach(invokeAndTest); > } > > I've added a "print(currentThreadName, java.lang.Thread. > currentThread().toString()); " to prove that currentThreadName stays the > same in all executions despite which Thread it is executing. > > > Check out this one now: > > @Test > public void testClosureThreadSafety2() throws ScriptException { > String testJsFunction = ( > " (function outerFunction(threadPointer) {\n" + > " function innerFunction() {\n" + > " return threadPointer().toString();\n" + > " }\n" + > " return innerFunction;\n" + > " })(java.lang.Thread.currentThread)\n"); > > ScriptObjectMirror jsFunction = (ScriptObjectMirror) > e.eval(testJsFunction); > > IntConsumer invokeAndTest = i-> { > Object received = jsFunction.call(jsFunction); > > Assert.assertEquals(Thread.currentThread().toString(), > received); > }; > IntStream.range(0, 10).parallel().forEach(invokeAndTest); > } > > Now there's a pointer to currentThread(not a string), and you can use it > in every thread returning different data. > > > > > > > > > Jo?o Varandas > *Arquiteto de Solu??es Cloud* > inPaaS - Id?ias em Aplica??es > > p: +55 11 5091-2777 <+55%2011%205091-2777> m: +55 11 99889-2321 > <+55%2011%2099889-2321> > a: Rua Nebraska, 443 - 1o Andar > Brooklin Paulista, S?o Paulo, SP > w: www.inpaas.com e: joaovarandas at inpaas.com > > > 2017-02-20 10:32 GMT-03:00 Frantzius, J?rg : > >> Hi Joao, >> >> the following test fails immediately for me with >> "java.lang.RuntimeException: Expected: Thread[ForkJoinPool.commonPool-worker-4,5,main], >> received: Thread[main,5,main]": >> >> @Test >> public void testClosureThreadSafety() throws ScriptException { >> final ScriptEngine engine = new ScriptEngineManager().getEngin >> eByName("nashorn"); >> >> String testJsFunction = ( >> " (function outerFunction(currentThreadName) {\n" + >> " function innerFunction() {\n" + >> " return currentThreadName;\n" + >> " }\n" + >> " return innerFunction;\n" + >> " })(java.lang.Thread.currentThread().toString())\n"); >> >> ScriptObjectMirror jsFunction = (ScriptObjectMirror) engine.eval( >> testJsFunction); >> >> IntConsumer invokeAndTest = i-> { >> String currentThreadName = Thread.currentThread().toString(); >> Object received = jsFunction.call(jsFunction); >> if (!currentThreadName.equals(received)) { >> throw new RuntimeException("Expected: " + >> currentThreadName + ", received: " + received); >> } >> }; >> IntStream.range(0, 10).parallel().forEach(invokeAndTest); >> } >> >> The outer function returns its inner function, which contains >> ?currentThread? as a reference to its closure (i.e. a reference to >> outerFunction?s ?currentThread? parameter). That closure property >> ?currentThread? will be set to the name of the current thread only once (in >> engine.eval(testJsFunction)), and subsequent calls to innerFunction will >> always return the name of that thread (and not of the current thread that >> calls innerFunction). >> >> If your Javascript code is under your control, this may not be a problem, >> as you can change the code. In our case, we are using an existing >> Javascript library ?Handlebars? that we cannot change, which seems to be >> keeping function objects with closures around just like the above code does >> in Java. >> >> Regards, >> J?rg >> >> Am 20.02.2017 um 13:00 schrieb Jo?o Paulo Varandas < >> joaovarandas at inpaas.com>: >> >> Hi Jorg. >> >> Could you send us a code snippet? >> >> I have never seem such problem when using closures. In my project, I use >> a single engine for whole web application. My tomcat is running with 150 >> maxThreads and it seems to be working fine. I test that in each build by >> running the test case below: >> >> https://gist.github.com/joaovarandas/f80a9cb5548a9d620e4da1ace2729911 >> >> The idea in this test is to use a single engine and run a closure from >> one-thread or multiple-threads simultaneously and then read data from those >> closures. >> >> >> PS.: Should I send the source code directly in the mail body for future >> readers? >> >> >> >> >> >> Jo?o Varandas >> *Arquiteto de Solu??es Cloud* >> inPaaS - Id?ias em Aplica??es >> >> p: +55 11 5091-2777 <+55%2011%205091-2777> m: +55 11 99889-2321 >> <+55%2011%2099889-2321> >> a: Rua Nebraska, 443 - 1o Andar >> Brooklin Paulista, S?o Paulo, SP >> w: www.inpaas.com e: joaovarandas at inpaas.com >> >> >> 2017-02-19 18:30 GMT-03:00 Frantzius, J?rg : >> >>> ? to correct myself, with code that contains closures, it?s probably >>> global-per-thread on a single engine that remains as the least >>> resource-consuming option (we were using a single global on single engine >>> for all threads, in order to share expensively computed Javascript state >>> between them). >>> >>> From what I understand, global-per-thread could be implemented e.g. by >>> having a ThreadLocal and always using that as the context in >>> ScriptEngine.eval(script, context). >>> >>> It would be good to know then whether global-per-thread on single engine >>> still allows for sharing Nashorn?s code optimization between threads? That >>> would already be great (and as Nashorn *is* great, I?m positive here :) >>> >>> Regards, >>> J?rg >>> >>> >>> Am 19.02.2017 um 00:47 schrieb Frantzius, J?rg < >>> Joerg.Frantzius at aperto.com>: >>> >>> Hi, >>> >>> it begins to dawn on me that closures aren?t thread-safe, at least that >>> would explain crosstalk issues we?re seeing in JMeter tests (with a single >>> engine for multiple threads). >>> >>> It would be good to know (and I guess for others as well) if somebody >>> can confirm this? >>> >>> Perhaps thread-safety of closures was thinkable if Nashorn somehow >>> stored closure state in ThreadLocals, but I guess that?s neither happening >>> nor planned? >>> >>> From what I understand, closures are pervasive in Javascript code out >>> there, and anybody using such code will currently be forced to use >>> engine-per-thread. >>> >>> Thanks for any hints, >>> J?rg >>> >>> >>> --- >>> >>> Dipl. Inf. J?rg von Frantzius, Technical Director >>> >>> E-Mail joerg.frantzius at aperto.com >>> >>> Phone +49 30 283921-318 >>> Fax +49 30 283921-29 >>> >>> Aperto GmbH ? An IBM Company >>> Chausseestra?e 5, D-10115 Berlin >>> http://www.aperto.com >>> http://www.facebook.com/aperto >>> https://www.xing.com/companies/apertoag >>> >>> HRB 77049 B, AG Berlin Charlottenburg >>> Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel >>> Simon >>> >>> >>> >>> --- >>> >>> Dipl. Inf. J?rg von Frantzius, Technical Director >>> >>> E-Mail joerg.frantzius at aperto.com >>> >>> Phone +49 30 283921-318 >>> Fax +49 30 283921-29 >>> >>> Aperto GmbH ? An IBM Company >>> Chausseestra?e 5, D-10115 Berlin >>> http://www.aperto.com >>> http://www.facebook.com/aperto >>> https://www.xing.com/companies/apertoag >>> >>> HRB 77049 B, AG Berlin Charlottenburg >>> Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel >>> Simon >>> >>> >> >> "Esta mensagem, incluindo seus anexos, pode conter informacoes >> confidenciais e privilegiadas. >> Se voce a recebeu por engano, solicitamos que a apague e avise o >> remetente imediatamente. >> Opinioes ou informacoes aqui contidas nao refletem necessariamente a >> posicao oficial da Plusoft." >> >> "Antes de imprimir, pense em sua responsabilidade e compromisso com o >> MEIO AMBIENTE" >> >> >> *---* >> >> *Dipl. Inf. J?rg von Frantzius, Technical Director* >> >> E-Mail joerg.frantzius at aperto.com >> >> Phone +49 30 283921-318 <+49%2030%20283921318> >> Fax +49 30 283921-29 <+49%2030%2028392129> >> >> Aperto GmbH ? An IBM Company >> Chausseestra?e 5, D-10115 Berlin >> http://www.aperto.com >> http://www.facebook.com/aperto >> https://www.xing.com/companies/apertoag >> >> HRB 77049 B, AG Berlin Charlottenburg >> Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel >> Simon >> >> > -- "Esta mensagem, incluindo seus anexos, pode conter informacoes confidenciais e privilegiadas. Se voce a recebeu por engano, solicitamos que a apague e avise o remetente imediatamente. Opinioes ou informacoes aqui contidas nao refletem necessariamente a posicao oficial da Plusoft." "Antes de imprimir, pense em sua responsabilidade e compromisso com o MEIO AMBIENTE" From Joerg.Frantzius at aperto.com Mon Feb 20 14:44:34 2017 From: Joerg.Frantzius at aperto.com (=?utf-8?B?RnJhbnR6aXVzLCBKw7ZyZw==?=) Date: Mon, 20 Feb 2017 14:44:34 +0000 Subject: Closures not thread-safe? In-Reply-To: References: <176720BC-74CA-4C83-96E2-5F2A6BFFC6BB@aperto.com> <562C5C98-48CB-40CD-9C2F-7344E8015208@aperto.com> Message-ID: Hi Joao, please see below. Am 20.02.2017 um 14:50 schrieb Jo?o Paulo Varandas >: There is no issue there. When your code is evaluated, currentThreadName is not a pointer to current thread name. It is a string, that has been evaluated only once. It won't change in different executions, remaining as "main" despite the executing thread(the closure has been created and it's variables are safely stored inside the closure). You are right, this is by design of Javascript closures, and there is no issue with Nashorn here (there may be an issue with my Javascript knowledge, though ;-) In your fix for the closure, you replaced the String object with a function object (that calls Thread.currentThread()). The test will fail equally if you move the brackets ?()? of the function invocation from the innerFunction into the last line of the JS, so that we?ll have a Thread object in the closure, see https://gist.github.com/jfrantzius/0a40c963413bdeabb51ecb13a769a436#file-nashornclosuretest-java-L45 It?s a nice fix if you have control of the Javascript code. Unfortunately, we?re using an existing Javascript library that wasn?t designed with multi-threading in mind, and we cannot change the code. So my point maybe then is that crosstalk issues with existing Javascript code may well be related to closures in that code. And I can also imagine that closures may cause headaches with someone?s own code, if it's supposed to be reentrant... Regards, J?rg Check out the changes in the code: @Test public void testClosureThreadSafety() throws ScriptException { String testJsFunction = ( " (function outerFunction(currentThreadName) {\n" + " function innerFunction() {\n" + " print(currentThreadName, java.lang.Thread.currentThread().toString()); return currentThreadName;\n" + " }\n" + " return innerFunction;\n" + " })(java.lang.Thread.currentThread().toString())\n"); ScriptObjectMirror jsFunction = (ScriptObjectMirror) e.eval(testJsFunction); String currentThreadName = Thread.currentThread().toString(); IntConsumer invokeAndTest = i-> { Object received = jsFunction.call(jsFunction); Assert.assertEquals(currentThreadName, received); }; IntStream.range(0, 10).parallel().forEach(invokeAndTest); } I've added a "print(currentThreadName, java.lang.Thread.currentThread().toString()); " to prove that currentThreadName stays the same in all executions despite which Thread it is executing. Check out this one now: @Test public void testClosureThreadSafety2() throws ScriptException { String testJsFunction = ( " (function outerFunction(threadPointer) {\n" + " function innerFunction() {\n" + " return threadPointer().toString();\n" + " }\n" + " return innerFunction;\n" + " })(java.lang.Thread.currentThread)\n"); ScriptObjectMirror jsFunction = (ScriptObjectMirror) e.eval(testJsFunction); IntConsumer invokeAndTest = i-> { Object received = jsFunction.call(jsFunction); Assert.assertEquals(Thread.currentThread().toString(), received); }; IntStream.range(0, 10).parallel().forEach(invokeAndTest); } Now there's a pointer to currentThread(not a string), and you can use it in every thread returning different data. [https://static.inpaas.com/assets/inpaas/images/logo-img-50px.png] Jo?o Varandas Arquiteto de Solu??es Cloud inPaaS - Id?ias em Aplica??es p: +55 11 5091-2777 m: +55 11 99889-2321 a: Rua Nebraska, 443 - 1o Andar Brooklin Paulista, S?o Paulo, SP w: www.inpaas.com e: joaovarandas at inpaas.com 2017-02-20 10:32 GMT-03:00 Frantzius, J?rg >: Hi Joao, the following test fails immediately for me with "java.lang.RuntimeException: Expected: Thread[ForkJoinPool.commonPool-worker-4,5,main], received: Thread[main,5,main]": @Test public void testClosureThreadSafety() throws ScriptException { final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); String testJsFunction = ( " (function outerFunction(currentThreadName) {\n" + " function innerFunction() {\n" + " return currentThreadName;\n" + " }\n" + " return innerFunction;\n" + " })(java.lang.Thread.currentThread().toString())\n"); ScriptObjectMirror jsFunction = (ScriptObjectMirror) engine.eval(testJsFunction); IntConsumer invokeAndTest = i-> { String currentThreadName = Thread.currentThread().toString(); Object received = jsFunction.call(jsFunction); if (!currentThreadName.equals(received)) { throw new RuntimeException("Expected: " + currentThreadName + ", received: " + received); } }; IntStream.range(0, 10).parallel().forEach(invokeAndTest); } The outer function returns its inner function, which contains ?currentThread? as a reference to its closure (i.e. a reference to outerFunction?s ?currentThread? parameter). That closure property ?currentThread? will be set to the name of the current thread only once (in engine.eval(testJsFunction)), and subsequent calls to innerFunction will always return the name of that thread (and not of the current thread that calls innerFunction). If your Javascript code is under your control, this may not be a problem, as you can change the code. In our case, we are using an existing Javascript library ?Handlebars? that we cannot change, which seems to be keeping function objects with closures around just like the above code does in Java. Regards, J?rg Am 20.02.2017 um 13:00 schrieb Jo?o Paulo Varandas >: Hi Jorg. Could you send us a code snippet? I have never seem such problem when using closures. In my project, I use a single engine for whole web application. My tomcat is running with 150 maxThreads and it seems to be working fine. I test that in each build by running the test case below: https://gist.github.com/joaovarandas/f80a9cb5548a9d620e4da1ace2729911 The idea in this test is to use a single engine and run a closure from one-thread or multiple-threads simultaneously and then read data from those closures. PS.: Should I send the source code directly in the mail body for future readers? [https://static.inpaas.com/assets/inpaas/images/logo-img-50px.png] Jo?o Varandas Arquiteto de Solu??es Cloud inPaaS - Id?ias em Aplica??es p: +55 11 5091-2777 m: +55 11 99889-2321 a: Rua Nebraska, 443 - 1o Andar Brooklin Paulista, S?o Paulo, SP w: www.inpaas.com e: joaovarandas at inpaas.com 2017-02-19 18:30 GMT-03:00 Frantzius, J?rg >: ? to correct myself, with code that contains closures, it?s probably global-per-thread on a single engine that remains as the least resource-consuming option (we were using a single global on single engine for all threads, in order to share expensively computed Javascript state between them). From what I understand, global-per-thread could be implemented e.g. by having a ThreadLocal and always using that as the context in ScriptEngine.eval(script, context). It would be good to know then whether global-per-thread on single engine still allows for sharing Nashorn?s code optimization between threads? That would already be great (and as Nashorn *is* great, I?m positive here :) Regards, J?rg Am 19.02.2017 um 00:47 schrieb Frantzius, J?rg >>: Hi, it begins to dawn on me that closures aren?t thread-safe, at least that would explain crosstalk issues we?re seeing in JMeter tests (with a single engine for multiple threads). It would be good to know (and I guess for others as well) if somebody can confirm this? Perhaps thread-safety of closures was thinkable if Nashorn somehow stored closure state in ThreadLocals, but I guess that?s neither happening nor planned? From what I understand, closures are pervasive in Javascript code out there, and anybody using such code will currently be forced to use engine-per-thread. Thanks for any hints, J?rg --- Dipl. Inf. J?rg von Frantzius, Technical Director E-Mail joerg.frantzius at aperto.com> Phone +49 30 283921-318 Fax +49 30 283921-29 Aperto GmbH ? An IBM Company Chausseestra?e 5, D-10115 Berlin http://www.aperto.com http://www.facebook.com/aperto https://www.xing.com/companies/apertoag HRB 77049 B, AG Berlin Charlottenburg Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel Simon --- Dipl. Inf. J?rg von Frantzius, Technical Director E-Mail joerg.frantzius at aperto.com Phone +49 30 283921-318 Fax +49 30 283921-29 Aperto GmbH ? An IBM Company Chausseestra?e 5, D-10115 Berlin http://www.aperto.com http://www.facebook.com/aperto https://www.xing.com/companies/apertoag HRB 77049 B, AG Berlin Charlottenburg Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel Simon "Esta mensagem, incluindo seus anexos, pode conter informacoes confidenciais e privilegiadas. Se voce a recebeu por engano, solicitamos que a apague e avise o remetente imediatamente. Opinioes ou informacoes aqui contidas nao refletem necessariamente a posicao oficial da Plusoft." "Antes de imprimir, pense em sua responsabilidade e compromisso com o MEIO AMBIENTE" --- Dipl. Inf. J?rg von Frantzius, Technical Director E-Mail joerg.frantzius at aperto.com Phone +49 30 283921-318 Fax +49 30 283921-29 Aperto GmbH ? An IBM Company Chausseestra?e 5, D-10115 Berlin http://www.aperto.com http://www.facebook.com/aperto https://www.xing.com/companies/apertoag HRB 77049 B, AG Berlin Charlottenburg Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel Simon "Esta mensagem, incluindo seus anexos, pode conter informacoes confidenciais e privilegiadas. Se voce a recebeu por engano, solicitamos que a apague e avise o remetente imediatamente. Opinioes ou informacoes aqui contidas nao refletem necessariamente a posicao oficial da Plusoft." "Antes de imprimir, pense em sua responsabilidade e compromisso com o MEIO AMBIENTE" --- Dipl. Inf. J?rg von Frantzius, Technical Director E-Mail joerg.frantzius at aperto.com Phone +49 30 283921-318 Fax +49 30 283921-29 Aperto GmbH ? An IBM Company Chausseestra?e 5, D-10115 Berlin http://www.aperto.com http://www.facebook.com/aperto https://www.xing.com/companies/apertoag HRB 77049 B, AG Berlin Charlottenburg Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel Simon From joaovarandas at inpaas.com Mon Feb 20 14:54:28 2017 From: joaovarandas at inpaas.com (=?UTF-8?Q?Jo=C3=A3o_Paulo_Varandas?=) Date: Mon, 20 Feb 2017 11:54:28 -0300 Subject: Closures not thread-safe? In-Reply-To: References: <176720BC-74CA-4C83-96E2-5F2A6BFFC6BB@aperto.com> <562C5C98-48CB-40CD-9C2F-7344E8015208@aperto.com> Message-ID: I get it now, maybe I didn't pay attention to your problem in the first place and was "fixated" by the thread safety idea. Nashorn has many ways to avoid those issues w/o the need for a new Engine. Depending on how the library works, you could use new Bindings for each Thread or Execution, but you may also test simply having a new Closure for each thread. Check it out: @Test public void testClosureThreadSafety() throws ScriptException { String testJsFunction = ( " (function outerFunction(currentThreadName) {\n" + " print(indx.incrementAndGet() + ' ' + java.lang.Thread.currentThread().toString() + ': closure data is ' + currentThreadName) \n" + " function innerFunction() {\n" + " return currentThreadName;\n" + " }\n" + " return innerFunction;\n" + " })(java.lang.Thread.currentThread().toString())\n"); e.getBindings(ScriptContext.GLOBAL_SCOPE).put("indx", new AtomicInteger(0)); ScriptObjectMirror jsFunction = (ScriptObjectMirror) e.eval(testJsFunction); String mainThreadName = Thread.currentThread().toString(); ThreadLocal innerjs = new ThreadLocal() { @Override public ScriptObjectMirror get() { try { return (ScriptObjectMirror) e.eval(testJsFunction); } catch(Exception e) { throw new RuntimeException(e); } } }; IntConsumer invokeAndTest = i -> { try { // my main closure is unchanged Assert.assertEquals(mainThreadName, jsFunction.call(jsFunction)); // since I have a new closure for each thread ... final ScriptObjectMirror innerJsFunction = innerjs.get(); final String currentThreadName = Thread.currentThread().toString(); Assert.assertEquals(currentThreadName, innerJsFunction.call(innerJsFunction)); } catch(Exception e) { throw new RuntimeException(e); } }; IntStream.range(0, 10).parallel().forEach(invokeAndTest); } Now we have different closures for each Thread, without the need of a new Engine or Bindings. Jo?o Varandas *Arquiteto de Solu??es Cloud* inPaaS - Id?ias em Aplica??es p: +55 11 5091-2777 m: +55 11 99889-2321 a: Rua Nebraska, 443 - 1o Andar Brooklin Paulista, S?o Paulo, SP w: www.inpaas.com e: joaovarandas at inpaas.com 2017-02-20 11:44 GMT-03:00 Frantzius, J?rg : > Hi Joao, > > please see below. > > Am 20.02.2017 um 14:50 schrieb Jo?o Paulo Varandas < > joaovarandas at inpaas.com>: > > There is no issue there. > When your code is evaluated, currentThreadName is not a pointer to current > thread name. It is a string, that has been evaluated only once. > > > It won't change in different executions, remaining as "main" despite the > executing thread(the closure has been created and it's variables are safely > stored inside the closure). > > > You are right, this is by design of Javascript closures, and there is no > issue with Nashorn here (there may be an issue with my Javascript > knowledge, though ;-) > > In your fix for the closure, you replaced the String object with a > function object (that calls Thread.currentThread()). The test will fail > equally if you move the brackets ?()? of the function invocation from the > innerFunction into the last line of the JS, so that we?ll have a Thread > object in the closure, see https://gist.github.com/jfrantzius/ > 0a40c963413bdeabb51ecb13a769a436#file-nashornclosuretest-java-L45 > > It?s a nice fix if you have control of the Javascript code. Unfortunately, > we?re using an existing Javascript library that wasn?t designed with > multi-threading in mind, and we cannot change the code. > > So my point maybe then is that crosstalk issues with existing Javascript > code may well be related to closures in that code. And I can also imagine > that closures may cause headaches with someone?s own code, if it's supposed > to be reentrant... > > Regards, > J?rg > > > Check out the changes in the code: > > @Test > public void testClosureThreadSafety() throws ScriptException { > String testJsFunction = ( > " (function outerFunction(currentThreadName) {\n" + > " function innerFunction() {\n" + > " print(currentThreadName, java.lang.Thread.currentThread().toString()); > return currentThreadName;\n" + > " }\n" + > " return innerFunction;\n" + > " })(java.lang.Thread.currentThread().toString())\n"); > > ScriptObjectMirror jsFunction = (ScriptObjectMirror) > e.eval(testJsFunction); > > String currentThreadName = Thread.currentThread().toString(); > > IntConsumer invokeAndTest = i-> { > Object received = jsFunction.call(jsFunction); > > Assert.assertEquals(currentThreadName, received); > }; > IntStream.range(0, 10).parallel().forEach(invokeAndTest); > } > > I've added a "print(currentThreadName, java.lang.Thread. > currentThread().toString()); " to prove that currentThreadName stays the > same in all executions despite which Thread it is executing. > > > Check out this one now: > > @Test > public void testClosureThreadSafety2() throws ScriptException { > String testJsFunction = ( > " (function outerFunction(threadPointer) {\n" + > " function innerFunction() {\n" + > " return threadPointer().toString();\n" + > " }\n" + > " return innerFunction;\n" + > " })(java.lang.Thread.currentThread)\n"); > > ScriptObjectMirror jsFunction = (ScriptObjectMirror) > e.eval(testJsFunction); > > IntConsumer invokeAndTest = i-> { > Object received = jsFunction.call(jsFunction); > > Assert.assertEquals(Thread.currentThread().toString(), > received); > }; > IntStream.range(0, 10).parallel().forEach(invokeAndTest); > } > > Now there's a pointer to currentThread(not a string), and you can use it > in every thread returning different data. > > > > > > > > > Jo?o Varandas > *Arquiteto de Solu??es Cloud* > inPaaS - Id?ias em Aplica??es > > p: +55 11 5091-2777 <+55%2011%205091-2777> m: +55 11 99889-2321 > <+55%2011%2099889-2321> > a: Rua Nebraska, 443 - 1o Andar > Brooklin Paulista, S?o Paulo, SP > w: www.inpaas.com e: joaovarandas at inpaas.com > > > 2017-02-20 10:32 GMT-03:00 Frantzius, J?rg : > >> Hi Joao, >> >> the following test fails immediately for me with >> "java.lang.RuntimeException: Expected: Thread[ForkJoinPool.commonPool-worker-4,5,main], >> received: Thread[main,5,main]": >> >> @Test >> public void testClosureThreadSafety() throws ScriptException { >> final ScriptEngine engine = new ScriptEngineManager().getEngin >> eByName("nashorn"); >> >> String testJsFunction = ( >> " (function outerFunction(currentThreadName) {\n" + >> " function innerFunction() {\n" + >> " return currentThreadName;\n" + >> " }\n" + >> " return innerFunction;\n" + >> " })(java.lang.Thread.currentThread().toString())\n"); >> >> ScriptObjectMirror jsFunction = (ScriptObjectMirror) engine.eval( >> testJsFunction); >> >> IntConsumer invokeAndTest = i-> { >> String currentThreadName = Thread.currentThread().toString(); >> Object received = jsFunction.call(jsFunction); >> if (!currentThreadName.equals(received)) { >> throw new RuntimeException("Expected: " + >> currentThreadName + ", received: " + received); >> } >> }; >> IntStream.range(0, 10).parallel().forEach(invokeAndTest); >> } >> >> The outer function returns its inner function, which contains >> ?currentThread? as a reference to its closure (i.e. a reference to >> outerFunction?s ?currentThread? parameter). That closure property >> ?currentThread? will be set to the name of the current thread only once (in >> engine.eval(testJsFunction)), and subsequent calls to innerFunction will >> always return the name of that thread (and not of the current thread that >> calls innerFunction). >> >> If your Javascript code is under your control, this may not be a problem, >> as you can change the code. In our case, we are using an existing >> Javascript library ?Handlebars? that we cannot change, which seems to be >> keeping function objects with closures around just like the above code does >> in Java. >> >> Regards, >> J?rg >> >> Am 20.02.2017 um 13:00 schrieb Jo?o Paulo Varandas < >> joaovarandas at inpaas.com>: >> >> Hi Jorg. >> >> Could you send us a code snippet? >> >> I have never seem such problem when using closures. In my project, I use >> a single engine for whole web application. My tomcat is running with 150 >> maxThreads and it seems to be working fine. I test that in each build by >> running the test case below: >> >> https://gist.github.com/joaovarandas/f80a9cb5548a9d620e4da1ace2729911 >> >> The idea in this test is to use a single engine and run a closure from >> one-thread or multiple-threads simultaneously and then read data from those >> closures. >> >> >> PS.: Should I send the source code directly in the mail body for future >> readers? >> >> >> >> >> >> Jo?o Varandas >> *Arquiteto de Solu??es Cloud* >> inPaaS - Id?ias em Aplica??es >> >> p: +55 11 5091-2777 <+55%2011%205091-2777> m: +55 11 99889-2321 >> <+55%2011%2099889-2321> >> a: Rua Nebraska, 443 - 1o Andar >> Brooklin Paulista, S?o Paulo, SP >> w: www.inpaas.com e: joaovarandas at inpaas.com >> >> >> 2017-02-19 18:30 GMT-03:00 Frantzius, J?rg : >> >>> ? to correct myself, with code that contains closures, it?s probably >>> global-per-thread on a single engine that remains as the least >>> resource-consuming option (we were using a single global on single engine >>> for all threads, in order to share expensively computed Javascript state >>> between them). >>> >>> From what I understand, global-per-thread could be implemented e.g. by >>> having a ThreadLocal and always using that as the context in >>> ScriptEngine.eval(script, context). >>> >>> It would be good to know then whether global-per-thread on single engine >>> still allows for sharing Nashorn?s code optimization between threads? That >>> would already be great (and as Nashorn *is* great, I?m positive here :) >>> >>> Regards, >>> J?rg >>> >>> >>> Am 19.02.2017 um 00:47 schrieb Frantzius, J?rg < >>> Joerg.Frantzius at aperto.com>: >>> >>> Hi, >>> >>> it begins to dawn on me that closures aren?t thread-safe, at least that >>> would explain crosstalk issues we?re seeing in JMeter tests (with a single >>> engine for multiple threads). >>> >>> It would be good to know (and I guess for others as well) if somebody >>> can confirm this? >>> >>> Perhaps thread-safety of closures was thinkable if Nashorn somehow >>> stored closure state in ThreadLocals, but I guess that?s neither happening >>> nor planned? >>> >>> From what I understand, closures are pervasive in Javascript code out >>> there, and anybody using such code will currently be forced to use >>> engine-per-thread. >>> >>> Thanks for any hints, >>> J?rg >>> >>> >>> --- >>> >>> Dipl. Inf. J?rg von Frantzius, Technical Director >>> >>> E-Mail joerg.frantzius at aperto.com >>> >>> Phone +49 30 283921-318 >>> Fax +49 30 283921-29 >>> >>> Aperto GmbH ? An IBM Company >>> Chausseestra?e 5, D-10115 Berlin >>> http://www.aperto.com >>> http://www.facebook.com/aperto >>> https://www.xing.com/companies/apertoag >>> >>> HRB 77049 B, AG Berlin Charlottenburg >>> Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel >>> Simon >>> >>> >>> >>> --- >>> >>> Dipl. Inf. J?rg von Frantzius, Technical Director >>> >>> E-Mail joerg.frantzius at aperto.com >>> >>> Phone +49 30 283921-318 >>> Fax +49 30 283921-29 >>> >>> Aperto GmbH ? An IBM Company >>> Chausseestra?e 5, D-10115 Berlin >>> http://www.aperto.com >>> http://www.facebook.com/aperto >>> https://www.xing.com/companies/apertoag >>> >>> HRB 77049 B, AG Berlin Charlottenburg >>> Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel >>> Simon >>> >>> >> >> "Esta mensagem, incluindo seus anexos, pode conter informacoes >> confidenciais e privilegiadas. >> Se voce a recebeu por engano, solicitamos que a apague e avise o >> remetente imediatamente. >> Opinioes ou informacoes aqui contidas nao refletem necessariamente a >> posicao oficial da Plusoft." >> >> "Antes de imprimir, pense em sua responsabilidade e compromisso com o >> MEIO AMBIENTE" >> >> >> *---* >> >> *Dipl. Inf. J?rg von Frantzius, Technical Director* >> >> E-Mail joerg.frantzius at aperto.com >> >> Phone +49 30 283921-318 <+49%2030%20283921318> >> Fax +49 30 283921-29 <+49%2030%2028392129> >> >> Aperto GmbH ? An IBM Company >> Chausseestra?e 5, D-10115 Berlin >> http://www.aperto.com >> http://www.facebook.com/aperto >> https://www.xing.com/companies/apertoag >> >> HRB 77049 B, AG Berlin Charlottenburg >> Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel >> Simon >> >> > > "Esta mensagem, incluindo seus anexos, pode conter informacoes > confidenciais e privilegiadas. > Se voce a recebeu por engano, solicitamos que a apague e avise o remetente > imediatamente. > Opinioes ou informacoes aqui contidas nao refletem necessariamente a > posicao oficial da Plusoft." > > "Antes de imprimir, pense em sua responsabilidade e compromisso com o MEIO > AMBIENTE" > > > *---* > > *Dipl. Inf. J?rg von Frantzius, Technical Director* > > E-Mail joerg.frantzius at aperto.com > > Phone +49 30 283921-318 <+49%2030%20283921318> > Fax +49 30 283921-29 <+49%2030%2028392129> > > Aperto GmbH ? An IBM Company > Chausseestra?e 5, D-10115 Berlin > http://www.aperto.com > http://www.facebook.com/aperto > https://www.xing.com/companies/apertoag > > HRB 77049 B, AG Berlin Charlottenburg > Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel > Simon > > -- "Esta mensagem, incluindo seus anexos, pode conter informacoes confidenciais e privilegiadas. Se voce a recebeu por engano, solicitamos que a apague e avise o remetente imediatamente. Opinioes ou informacoes aqui contidas nao refletem necessariamente a posicao oficial da Plusoft." "Antes de imprimir, pense em sua responsabilidade e compromisso com o MEIO AMBIENTE" From joaovarandas at inpaas.com Mon Feb 20 15:11:44 2017 From: joaovarandas at inpaas.com (=?UTF-8?Q?Jo=C3=A3o_Paulo_Varandas?=) Date: Mon, 20 Feb 2017 12:11:44 -0300 Subject: Closures not thread-safe? In-Reply-To: References: <176720BC-74CA-4C83-96E2-5F2A6BFFC6BB@aperto.com> <562C5C98-48CB-40CD-9C2F-7344E8015208@aperto.com> Message-ID: What I intended with that test, is that you can try having handlebars evaluated in each Thread(using ThreadLocal maybe) and they will have their own values. As long as handlebars code do not use any global objects. By the way, that code has been executed 1.000.000 times in 3 seconds, using range(0, 999999), so it's scaled pretty nicely in my developer machine. In the other hand, having a new ScriptEngine for each thread may not scale so well ... Anyway, it was a good exercise of closures, bindings and engines. I hope those samples helped you out achieving what you need. Also, if it's an option, you could check out jknack's handlebars: https://github.com/jknack/handlebars.java Which is a Java implementation with thread-safety. Jo?o Varandas *Arquiteto de Solu??es Cloud* inPaaS - Id?ias em Aplica??es p: +55 11 5091-2777 m: +55 11 99889-2321 a: Rua Nebraska, 443 - 1o Andar Brooklin Paulista, S?o Paulo, SP w: www.inpaas.com e: joaovarandas at inpaas.com 2017-02-20 11:54 GMT-03:00 Jo?o Paulo Varandas : > I get it now, maybe I didn't pay attention to your problem in the first > place and was "fixated" by the thread safety idea. > > Nashorn has many ways to avoid those issues w/o the need for a new Engine. > Depending on how the library works, you could use new Bindings for each > Thread or Execution, but you may also test simply having a new Closure for > each thread. Check it out: > > > @Test > public void testClosureThreadSafety() throws ScriptException { > String testJsFunction = ( > " (function outerFunction(currentThreadName) {\n" + > " print(indx.incrementAndGet() + ' ' + > java.lang.Thread.currentThread().toString() + ': closure data is ' + > currentThreadName) \n" + > " function innerFunction() {\n" + > " return currentThreadName;\n" + > " }\n" + > " return innerFunction;\n" + > " })(java.lang.Thread.currentThread().toString())\n"); > > e.getBindings(ScriptContext.GLOBAL_SCOPE).put("indx", new > AtomicInteger(0)); > ScriptObjectMirror jsFunction = (ScriptObjectMirror) > e.eval(testJsFunction); > > String mainThreadName = Thread.currentThread().toString(); > > ThreadLocal innerjs = new ThreadLocal() > { > @Override > public ScriptObjectMirror get() { > try { > return (ScriptObjectMirror) e.eval(testJsFunction); > } catch(Exception e) { > throw new RuntimeException(e); > > } > } > > }; > > IntConsumer invokeAndTest = i -> { > try { > // my main closure is unchanged > Assert.assertEquals(mainThreadName, jsFunction.call(jsFunction)); > > // since I have a new closure for each thread ... > final ScriptObjectMirror innerJsFunction = innerjs.get(); > final String currentThreadName = Thread.currentThread(). > toString(); > Assert.assertEquals(currentThreadName, > innerJsFunction.call(innerJsFunction)); > > } catch(Exception e) { > throw new RuntimeException(e); > } > > }; > IntStream.range(0, 10).parallel().forEach(invokeAndTest); > } > > > Now we have different closures for each Thread, without the need of a new > Engine or Bindings. > > > > > > Jo?o Varandas > *Arquiteto de Solu??es Cloud* > inPaaS - Id?ias em Aplica??es > > p: +55 11 5091-2777 <+55%2011%205091-2777> m: +55 11 99889-2321 > <+55%2011%2099889-2321> > a: Rua Nebraska, 443 - 1o Andar > Brooklin Paulista, S?o Paulo, SP > w: www.inpaas.com e: joaovarandas at inpaas.com > > > 2017-02-20 11:44 GMT-03:00 Frantzius, J?rg : > >> Hi Joao, >> >> please see below. >> >> Am 20.02.2017 um 14:50 schrieb Jo?o Paulo Varandas < >> joaovarandas at inpaas.com>: >> >> There is no issue there. >> When your code is evaluated, currentThreadName is not a pointer to >> current thread name. It is a string, that has been evaluated only once. >> >> >> It won't change in different executions, remaining as "main" despite the >> executing thread(the closure has been created and it's variables are safely >> stored inside the closure). >> >> >> You are right, this is by design of Javascript closures, and there is no >> issue with Nashorn here (there may be an issue with my Javascript >> knowledge, though ;-) >> >> In your fix for the closure, you replaced the String object with a >> function object (that calls Thread.currentThread()). The test will fail >> equally if you move the brackets ?()? of the function invocation from the >> innerFunction into the last line of the JS, so that we?ll have a Thread >> object in the closure, see https://gist.github.com/jfrant >> zius/0a40c963413bdeabb51ecb13a769a436#file-nashornclosuretest-java-L45 >> >> It?s a nice fix if you have control of the Javascript code. >> Unfortunately, we?re using an existing Javascript library that wasn?t >> designed with multi-threading in mind, and we cannot change the code. >> >> So my point maybe then is that crosstalk issues with existing Javascript >> code may well be related to closures in that code. And I can also imagine >> that closures may cause headaches with someone?s own code, if it's supposed >> to be reentrant... >> >> Regards, >> J?rg >> >> >> Check out the changes in the code: >> >> @Test >> public void testClosureThreadSafety() throws ScriptException { >> String testJsFunction = ( >> " (function outerFunction(currentThreadName) {\n" + >> " function innerFunction() {\n" + >> " print(currentThreadName, >> java.lang.Thread.currentThread().toString()); return >> currentThreadName;\n" + >> " }\n" + >> " return innerFunction;\n" + >> " })(java.lang.Thread.currentThread().toString())\n"); >> >> ScriptObjectMirror jsFunction = (ScriptObjectMirror) >> e.eval(testJsFunction); >> >> String currentThreadName = Thread.currentThread().toString(); >> >> IntConsumer invokeAndTest = i-> { >> Object received = jsFunction.call(jsFunction); >> >> Assert.assertEquals(currentThreadName, received); >> }; >> IntStream.range(0, 10).parallel().forEach(invokeAndTest); >> } >> >> I've added a "print(currentThreadName, java.lang.Thread.currentThread >> ().toString()); " to prove that currentThreadName stays the same in all >> executions despite which Thread it is executing. >> >> >> Check out this one now: >> >> @Test >> public void testClosureThreadSafety2() throws ScriptException { >> String testJsFunction = ( >> " (function outerFunction(threadPointer) {\n" + >> " function innerFunction() {\n" + >> " return threadPointer().toString();\n" + >> " }\n" + >> " return innerFunction;\n" + >> " })(java.lang.Thread.currentThread)\n"); >> >> ScriptObjectMirror jsFunction = (ScriptObjectMirror) >> e.eval(testJsFunction); >> >> IntConsumer invokeAndTest = i-> { >> Object received = jsFunction.call(jsFunction); >> >> Assert.assertEquals(Thread.currentThread().toString(), >> received); >> }; >> IntStream.range(0, 10).parallel().forEach(invokeAndTest); >> } >> >> Now there's a pointer to currentThread(not a string), and you can use it >> in every thread returning different data. >> >> >> >> >> >> >> >> >> Jo?o Varandas >> *Arquiteto de Solu??es Cloud* >> inPaaS - Id?ias em Aplica??es >> >> p: +55 11 5091-2777 <+55%2011%205091-2777> m: +55 11 99889-2321 >> <+55%2011%2099889-2321> >> a: Rua Nebraska, 443 - 1o Andar >> Brooklin Paulista, S?o Paulo, SP >> w: www.inpaas.com e: joaovarandas at inpaas.com >> >> >> 2017-02-20 10:32 GMT-03:00 Frantzius, J?rg : >> >>> Hi Joao, >>> >>> the following test fails immediately for me with >>> "java.lang.RuntimeException: Expected: Thread[ForkJoinPool.commonPool-worker-4,5,main], >>> received: Thread[main,5,main]": >>> >>> @Test >>> public void testClosureThreadSafety() throws ScriptException { >>> final ScriptEngine engine = new ScriptEngineManager().getEngin >>> eByName("nashorn"); >>> >>> String testJsFunction = ( >>> " (function outerFunction(currentThreadName) {\n" + >>> " function innerFunction() {\n" + >>> " return currentThreadName;\n" + >>> " }\n" + >>> " return innerFunction;\n" + >>> " })(java.lang.Thread.currentThread().toString())\n"); >>> >>> ScriptObjectMirror jsFunction = (ScriptObjectMirror) engine >>> .eval(testJsFunction); >>> >>> IntConsumer invokeAndTest = i-> { >>> String currentThreadName = Thread.currentThread().toStrin >>> g(); >>> Object received = jsFunction.call(jsFunction); >>> if (!currentThreadName.equals(received)) { >>> throw new RuntimeException("Expected: " + >>> currentThreadName + ", received: " + received); >>> } >>> }; >>> IntStream.range(0, 10).parallel().forEach(invokeAndTest); >>> } >>> >>> The outer function returns its inner function, which contains >>> ?currentThread? as a reference to its closure (i.e. a reference to >>> outerFunction?s ?currentThread? parameter). That closure property >>> ?currentThread? will be set to the name of the current thread only once (in >>> engine.eval(testJsFunction)), and subsequent calls to innerFunction will >>> always return the name of that thread (and not of the current thread that >>> calls innerFunction). >>> >>> If your Javascript code is under your control, this may not be a >>> problem, as you can change the code. In our case, we are using an existing >>> Javascript library ?Handlebars? that we cannot change, which seems to be >>> keeping function objects with closures around just like the above code does >>> in Java. >>> >>> Regards, >>> J?rg >>> >>> Am 20.02.2017 um 13:00 schrieb Jo?o Paulo Varandas < >>> joaovarandas at inpaas.com>: >>> >>> Hi Jorg. >>> >>> Could you send us a code snippet? >>> >>> I have never seem such problem when using closures. In my project, I use >>> a single engine for whole web application. My tomcat is running with 150 >>> maxThreads and it seems to be working fine. I test that in each build by >>> running the test case below: >>> >>> https://gist.github.com/joaovarandas/f80a9cb5548a9d620e4da1ace2729911 >>> >>> The idea in this test is to use a single engine and run a closure from >>> one-thread or multiple-threads simultaneously and then read data from those >>> closures. >>> >>> >>> PS.: Should I send the source code directly in the mail body for future >>> readers? >>> >>> >>> >>> >>> >>> Jo?o Varandas >>> *Arquiteto de Solu??es Cloud* >>> inPaaS - Id?ias em Aplica??es >>> >>> p: +55 11 5091-2777 <+55%2011%205091-2777> m: +55 11 99889-2321 >>> <+55%2011%2099889-2321> >>> a: Rua Nebraska, 443 - 1o Andar >>> Brooklin Paulista, S?o Paulo, SP >>> w: www.inpaas.com e: joaovarandas at inpaas.com >>> >>> >>> 2017-02-19 18:30 GMT-03:00 Frantzius, J?rg : >>> >>>> ? to correct myself, with code that contains closures, it?s probably >>>> global-per-thread on a single engine that remains as the least >>>> resource-consuming option (we were using a single global on single engine >>>> for all threads, in order to share expensively computed Javascript state >>>> between them). >>>> >>>> From what I understand, global-per-thread could be implemented e.g. by >>>> having a ThreadLocal and always using that as the context in >>>> ScriptEngine.eval(script, context). >>>> >>>> It would be good to know then whether global-per-thread on single >>>> engine still allows for sharing Nashorn?s code optimization between >>>> threads? That would already be great (and as Nashorn *is* great, I?m >>>> positive here :) >>>> >>>> Regards, >>>> J?rg >>>> >>>> >>>> Am 19.02.2017 um 00:47 schrieb Frantzius, J?rg < >>>> Joerg.Frantzius at aperto.com>: >>>> >>>> Hi, >>>> >>>> it begins to dawn on me that closures aren?t thread-safe, at least that >>>> would explain crosstalk issues we?re seeing in JMeter tests (with a single >>>> engine for multiple threads). >>>> >>>> It would be good to know (and I guess for others as well) if somebody >>>> can confirm this? >>>> >>>> Perhaps thread-safety of closures was thinkable if Nashorn somehow >>>> stored closure state in ThreadLocals, but I guess that?s neither happening >>>> nor planned? >>>> >>>> From what I understand, closures are pervasive in Javascript code out >>>> there, and anybody using such code will currently be forced to use >>>> engine-per-thread. >>>> >>>> Thanks for any hints, >>>> J?rg >>>> >>>> >>>> --- >>>> >>>> Dipl. Inf. J?rg von Frantzius, Technical Director >>>> >>>> E-Mail joerg.frantzius at aperto.com >>>> >>>> Phone +49 30 283921-318 >>>> Fax +49 30 283921-29 >>>> >>>> Aperto GmbH ? An IBM Company >>>> Chausseestra?e 5, D-10115 Berlin >>>> http://www.aperto.com >>>> http://www.facebook.com/aperto >>>> https://www.xing.com/companies/apertoag >>>> >>>> HRB 77049 B, AG Berlin Charlottenburg >>>> Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel >>>> Simon >>>> >>>> >>>> >>>> --- >>>> >>>> Dipl. Inf. J?rg von Frantzius, Technical Director >>>> >>>> E-Mail joerg.frantzius at aperto.com >>>> >>>> Phone +49 30 283921-318 >>>> Fax +49 30 283921-29 >>>> >>>> Aperto GmbH ? An IBM Company >>>> Chausseestra?e 5, D-10115 Berlin >>>> http://www.aperto.com >>>> http://www.facebook.com/aperto >>>> https://www.xing.com/companies/apertoag >>>> >>>> HRB 77049 B, AG Berlin Charlottenburg >>>> Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel >>>> Simon >>>> >>>> >>> >>> "Esta mensagem, incluindo seus anexos, pode conter informacoes >>> confidenciais e privilegiadas. >>> Se voce a recebeu por engano, solicitamos que a apague e avise o >>> remetente imediatamente. >>> Opinioes ou informacoes aqui contidas nao refletem necessariamente a >>> posicao oficial da Plusoft." >>> >>> "Antes de imprimir, pense em sua responsabilidade e compromisso com o >>> MEIO AMBIENTE" >>> >>> >>> *---* >>> >>> *Dipl. Inf. J?rg von Frantzius, Technical Director* >>> >>> E-Mail joerg.frantzius at aperto.com >>> >>> Phone +49 30 283921-318 <+49%2030%20283921318> >>> Fax +49 30 283921-29 <+49%2030%2028392129> >>> >>> Aperto GmbH ? An IBM Company >>> Chausseestra?e 5, D-10115 Berlin >>> http://www.aperto.com >>> http://www.facebook.com/aperto >>> https://www.xing.com/companies/apertoag >>> >>> HRB 77049 B, AG Berlin Charlottenburg >>> Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel >>> Simon >>> >>> >> >> "Esta mensagem, incluindo seus anexos, pode conter informacoes >> confidenciais e privilegiadas. >> Se voce a recebeu por engano, solicitamos que a apague e avise o >> remetente imediatamente. >> Opinioes ou informacoes aqui contidas nao refletem necessariamente a >> posicao oficial da Plusoft." >> >> "Antes de imprimir, pense em sua responsabilidade e compromisso com o >> MEIO AMBIENTE" >> >> >> *---* >> >> *Dipl. Inf. J?rg von Frantzius, Technical Director* >> >> E-Mail joerg.frantzius at aperto.com >> >> Phone +49 30 283921-318 <+49%2030%20283921318> >> Fax +49 30 283921-29 <+49%2030%2028392129> >> >> Aperto GmbH ? An IBM Company >> Chausseestra?e 5, D-10115 Berlin >> http://www.aperto.com >> http://www.facebook.com/aperto >> https://www.xing.com/companies/apertoag >> >> HRB 77049 B, AG Berlin Charlottenburg >> Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel >> Simon >> >> > -- "Esta mensagem, incluindo seus anexos, pode conter informacoes confidenciais e privilegiadas. Se voce a recebeu por engano, solicitamos que a apague e avise o remetente imediatamente. Opinioes ou informacoes aqui contidas nao refletem necessariamente a posicao oficial da Plusoft." "Antes de imprimir, pense em sua responsabilidade e compromisso com o MEIO AMBIENTE" From Joerg.Frantzius at aperto.com Mon Feb 20 17:03:43 2017 From: Joerg.Frantzius at aperto.com (=?utf-8?B?RnJhbnR6aXVzLCBKw7ZyZw==?=) Date: Mon, 20 Feb 2017 17:03:43 +0000 Subject: Closures not thread-safe? In-Reply-To: References: <176720BC-74CA-4C83-96E2-5F2A6BFFC6BB@aperto.com> <562C5C98-48CB-40CD-9C2F-7344E8015208@aperto.com> Message-ID: <14367A0E-5557-4DFA-B879-541DEEE5627A@aperto.com> Hi Joao, as you are overriding ThreadLocal.get(), the effect is that testJsFunction is simply eval()ed anew by every thread, so each thread creates its own closure. (I guess it?s never a good idea to override ThreadLocal.get() without calling super.get() at all ?) But anyway, the real problem I have is probably mutation of a closure. That?s possible if the closure is over a mutable object, like a HashMap. Closure mutation works both in the same thread: https://gist.github.com/jfrantzius/0a40c963413bdeabb51ecb13a769a436#file-nashornclosuretest-java-L138 As well as in another thread: https://gist.github.com/jfrantzius/0a40c963413bdeabb51ecb13a769a436#file-nashornclosuretest-java-L166 I guess my initial proposal of Nashorn performing some magical closure resolution with ThreadLocals is just bogus. I?ll go for dedicated global per thread, and as an optimization, I?ll pool them. Thanks for being helpful + cheers from Berlin, J?rg Am 20.02.2017 um 15:54 schrieb Jo?o Paulo Varandas >: @Test public void testClosureThreadSafety() throws ScriptException { String testJsFunction = ( " (function outerFunction(currentThreadName) {\n" + " print(indx.incrementAndGet() + ' ' + java.lang.Thread.currentThread().toString() + ': closure data is ' + currentThreadName) \n" + " function innerFunction() {\n" + " return currentThreadName;\n" + " }\n" + " return innerFunction;\n" + " })(java.lang.Thread.currentThread().toString())\n"); e.getBindings(ScriptContext.GLOBAL_SCOPE).put("indx", new AtomicInteger(0)); ScriptObjectMirror jsFunction = (ScriptObjectMirror) e.eval(testJsFunction); String mainThreadName = Thread.currentThread().toString(); ThreadLocal innerjs = new ThreadLocal() { @Override public ScriptObjectMirror get() { try { return (ScriptObjectMirror) e.eval(testJsFunction); } catch(Exception e) { throw new RuntimeException(e); } } }; IntConsumer invokeAndTest = i -> { try { // my main closure is unchanged Assert.assertEquals(mainThreadName, jsFunction.call(jsFunction)); // since I have a new closure for each thread ... final ScriptObjectMirror innerJsFunction = innerjs.get(); final String currentThreadName = Thread.currentThread().toString(); Assert.assertEquals(currentThreadName, innerJsFunction.call(innerJsFunction)); } catch(Exception e) { throw new RuntimeException(e); } }; IntStream.range(0, 10).parallel().forEach(invokeAndTest); } --- Dipl. Inf. J?rg von Frantzius, Technical Director E-Mail joerg.frantzius at aperto.com Phone +49 30 283921-318 Fax +49 30 283921-29 Aperto GmbH ? An IBM Company Chausseestra?e 5, D-10115 Berlin http://www.aperto.com http://www.facebook.com/aperto https://www.xing.com/companies/apertoag HRB 77049 B, AG Berlin Charlottenburg Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel Simon From joaovarandas at inpaas.com Mon Feb 20 17:25:36 2017 From: joaovarandas at inpaas.com (=?UTF-8?Q?Jo=C3=A3o_Paulo_Varandas?=) Date: Mon, 20 Feb 2017 14:25:36 -0300 Subject: Closures not thread-safe? In-Reply-To: <14367A0E-5557-4DFA-B879-541DEEE5627A@aperto.com> References: <176720BC-74CA-4C83-96E2-5F2A6BFFC6BB@aperto.com> <562C5C98-48CB-40CD-9C2F-7344E8015208@aperto.com> <14367A0E-5557-4DFA-B879-541DEEE5627A@aperto.com> Message-ID: Oops... You're right, my code evaluates the closure every time. Changing 'get' to 'initialValue' will achieve it's purpose, sorry about that. It seems you have a nice use case over there, multi-threading is always tricky and JavaScript adds another level of challenge, since sometimes takes time to understand how the engine works at all(closures, lexical vs dynamic scopes and global vars). Anyway, good luck on your research and you're welcome, I'm glad that I could help a little bit. Cheers from Brazil! Jp 2017-02-20 14:03 GMT-03:00 Frantzius, J?rg : > Hi Joao, > > as you are overriding ThreadLocal.get(), the effect is that testJsFunction > is simply eval()ed anew by every thread, so each thread creates its own > closure. (I guess it?s never a good idea to override ThreadLocal.get() > without calling super.get() at all ?) > > But anyway, the real problem I have is probably mutation of a closure. > That?s possible if the closure is over a mutable object, like a HashMap. > > Closure mutation works both in the same thread: https://gist.github. > com/jfrantzius/0a40c963413bdeabb51ecb13a769a436#file-nashornclosuretest- > java-L138 > As well as in another thread: https://gist.github.com/jfrantzius/ > 0a40c963413bdeabb51ecb13a769a436#file-nashornclosuretest-java-L166 > > I guess my initial proposal of Nashorn performing some magical closure > resolution with ThreadLocals is just bogus. > > I?ll go for dedicated global per thread, and as an optimization, I?ll pool > them. > > Thanks for being helpful + cheers from Berlin, > J?rg > > > Am 20.02.2017 um 15:54 schrieb Jo?o Paulo Varandas < > joaovarandas at inpaas.com>: > > @Test > public void testClosureThreadSafety() throws ScriptException { > String testJsFunction = ( > " (function outerFunction(currentThreadName) {\n" + > " print(indx.incrementAndGet() + ' ' + > java.lang.Thread.currentThread().toString() + ': closure data is ' + > currentThreadName) \n" + > " function innerFunction() {\n" + > " return currentThreadName;\n" + > " }\n" + > " return innerFunction;\n" + > " })(java.lang.Thread.currentThread().toString())\n"); > > e.getBindings(ScriptContext.GLOBAL_SCOPE).put("indx", new > AtomicInteger(0)); > ScriptObjectMirror jsFunction = (ScriptObjectMirror) > e.eval(testJsFunction); > > String mainThreadName = Thread.currentThread().toString(); > > ThreadLocal innerjs = new ThreadLocal() > { > @Override > public ScriptObjectMirror get() { > try { > return (ScriptObjectMirror) e.eval(testJsFunction); > } catch(Exception e) { > throw new RuntimeException(e); > > } > } > > }; > > IntConsumer invokeAndTest = i -> { > try { > // my main closure is unchanged > Assert.assertEquals(mainThreadName, jsFunction.call(jsFunction)); > > // since I have a new closure for each thread ... > final ScriptObjectMirror innerJsFunction = innerjs.get(); > final String currentThreadName = Thread.currentThread(). > toString(); > Assert.assertEquals(currentThreadName, > innerJsFunction.call(innerJsFunction)); > > } catch(Exception e) { > throw new RuntimeException(e); > } > > }; > IntStream.range(0, 10).parallel().forEach(invokeAndTest); > } > > > *---* > > *Dipl. Inf. J?rg von Frantzius, Technical Director* > > E-Mail joerg.frantzius at aperto.com > > Phone +49 30 283921-318 <+49%2030%20283921318> > Fax +49 30 283921-29 <+49%2030%2028392129> > > Aperto GmbH ? An IBM Company > Chausseestra?e 5, D-10115 Berlin > http://www.aperto.com > http://www.facebook.com/aperto > https://www.xing.com/companies/apertoag > > HRB 77049 B, AG Berlin Charlottenburg > Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel > Simon > > -- "Esta mensagem, incluindo seus anexos, pode conter informacoes confidenciais e privilegiadas. Se voce a recebeu por engano, solicitamos que a apague e avise o remetente imediatamente. Opinioes ou informacoes aqui contidas nao refletem necessariamente a posicao oficial da Plusoft." "Antes de imprimir, pense em sua responsabilidade e compromisso com o MEIO AMBIENTE" From burakkoray at gmail.com Sat Feb 25 09:24:31 2017 From: burakkoray at gmail.com (Koray) Date: Sat, 25 Feb 2017 11:24:31 +0200 Subject: Getting Input From User Message-ID: Hello, I apologize if this is not the place to ask, but I couldn't get a satisfying answer from anywhere else so this is kind of my last resort. Is there any built-in function to get input from a user when using NashornScriptEngine? print() method allows us to utilize both the default OutputStreamWriter (System.out) and any writers that we set using ScriptContext, but how can I make use of the reader which is used by the engine? Thank you, Burak From james.laskey at oracle.com Sat Feb 25 14:34:05 2017 From: james.laskey at oracle.com (Jim Laskey (Oracle)) Date: Sat, 25 Feb 2017 10:34:05 -0400 Subject: Getting Input From User In-Reply-To: References: Message-ID: <6D7BA1EC-F4EE-415D-B280-F57265F4A452@oracle.com> >> jjs -scripting jjs> var name = readLine("Your name >> "); Your name >> Jim jjs> print(name) Jim That sort of thing? ? Jim > On Feb 25, 2017, at 5:24 AM, Koray wrote: > > Hello, > > I apologize if this is not the place to ask, but I couldn't get a > satisfying answer from anywhere else so this is kind of my last > resort. > > Is there any built-in function to get input from a user when using > NashornScriptEngine? print() method allows us to utilize both the > default OutputStreamWriter (System.out) and any writers that we set > using ScriptContext, but how can I make use of the reader which is > used by the engine? > > Thank you, > Burak From burakkoray at gmail.com Sat Feb 25 17:41:51 2017 From: burakkoray at gmail.com (Koray) Date: Sat, 25 Feb 2017 19:41:51 +0200 Subject: Getting Input From User In-Reply-To: <6D7BA1EC-F4EE-415D-B280-F57265F4A452@oracle.com> References: <6D7BA1EC-F4EE-415D-B280-F57265F4A452@oracle.com> Message-ID: This is exactly what I'm looking for. Is it possible to do this from inside a Java application? I have tried readLine() and readFully() methods before, but I'm guessing they are meant for the commandline tool only. Burak On 2/25/17, Jim Laskey (Oracle) wrote: >>> jjs -scripting > jjs> var name = readLine("Your name >> "); > Your name >> Jim > jjs> print(name) > Jim > > That sort of thing? > > ? Jim > > >> On Feb 25, 2017, at 5:24 AM, Koray wrote: >> >> Hello, >> >> I apologize if this is not the place to ask, but I couldn't get a >> satisfying answer from anywhere else so this is kind of my last >> resort. >> >> Is there any built-in function to get input from a user when using >> NashornScriptEngine? print() method allows us to utilize both the >> default OutputStreamWriter (System.out) and any writers that we set >> using ScriptContext, but how can I make use of the reader which is >> used by the engine? >> >> Thank you, >> Burak > > -- sayg?lar?mla Burak Koray Polat From forax at univ-mlv.fr Sat Feb 25 18:31:27 2017 From: forax at univ-mlv.fr (Remi Forax) Date: Sat, 25 Feb 2017 19:31:27 +0100 (CET) Subject: Getting Input From User In-Reply-To: References: <6D7BA1EC-F4EE-415D-B280-F57265F4A452@oracle.com> Message-ID: <1006240691.2354250.1488047487892.JavaMail.zimbra@u-pem.fr> In Java, you can use the Console: System.console().readLine("") with the caveat that System.console() [1] can return null if no terminal is attached to the process. Otherwise you can use a Scanner: Scanner scanner = new Scanner(System.in); scanner.nextLine() or a BufferedReader: BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); reader.readLine() or reader.lines() if you want a Stream of all lines. cheers, R?mi [1] http://download.java.net/java/jdk9/docs/api/java/lang/System.html#console-- ----- Mail original ----- > De: "Koray" > ?: "Jim Laskey (Oracle)" > Cc: nashorn-dev at openjdk.java.net > Envoy?: Samedi 25 F?vrier 2017 18:41:51 > Objet: Re: Getting Input From User > This is exactly what I'm looking for. Is it possible to do this from > inside a Java application? I have tried readLine() and readFully() > methods before, but I'm guessing they are meant for the commandline > tool only. > > Burak > On 2/25/17, Jim Laskey (Oracle) wrote: >>>> jjs -scripting >> jjs> var name = readLine("Your name >> "); >> Your name >> Jim >> jjs> print(name) >> Jim >> >> That sort of thing? >> >> ? Jim >> >> >>> On Feb 25, 2017, at 5:24 AM, Koray wrote: >>> >>> Hello, >>> >>> I apologize if this is not the place to ask, but I couldn't get a >>> satisfying answer from anywhere else so this is kind of my last >>> resort. >>> >>> Is there any built-in function to get input from a user when using >>> NashornScriptEngine? print() method allows us to utilize both the >>> default OutputStreamWriter (System.out) and any writers that we set >>> using ScriptContext, but how can I make use of the reader which is >>> used by the engine? >>> >>> Thank you, >>> Burak >> >> > > > -- > sayg?lar?mla > Burak Koray Polat From james.laskey at oracle.com Sat Feb 25 19:31:21 2017 From: james.laskey at oracle.com (James Laskey) Date: Sat, 25 Feb 2017 15:31:21 -0400 Subject: Getting Input From User In-Reply-To: References: <6D7BA1EC-F4EE-415D-B280-F57265F4A452@oracle.com> Message-ID: <194CA109-893A-459A-A757-AE3D0FB4245B@oracle.com> You have to be in scripting mode to to use those functions. https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/shell.html. It's possible to add command line options when using from java. https://wiki.openjdk.java.net/display/Nashorn/Nashorn+jsr223+engine+notes -- Jim Sent from my iPhone > On Feb 25, 2017, at 1:41 PM, Koray wrote: > > This is exactly what I'm looking for. Is it possible to do this from > inside a Java application? I have tried readLine() and readFully() > methods before, but I'm guessing they are meant for the commandline > tool only. > > Burak > On 2/25/17, Jim Laskey (Oracle) wrote: >>>> jjs -scripting >> jjs> var name = readLine("Your name >> "); >> Your name >> Jim >> jjs> print(name) >> Jim >> >> That sort of thing? >> >> ? Jim >> >> >>> On Feb 25, 2017, at 5:24 AM, Koray wrote: >>> >>> Hello, >>> >>> I apologize if this is not the place to ask, but I couldn't get a >>> satisfying answer from anywhere else so this is kind of my last >>> resort. >>> >>> Is there any built-in function to get input from a user when using >>> NashornScriptEngine? print() method allows us to utilize both the >>> default OutputStreamWriter (System.out) and any writers that we set >>> using ScriptContext, but how can I make use of the reader which is >>> used by the engine? >>> >>> Thank you, >>> Burak >> >> > > > -- > sayg?lar?mla > Burak Koray Polat From burakkoray at gmail.com Sun Feb 26 04:51:37 2017 From: burakkoray at gmail.com (Koray) Date: Sun, 26 Feb 2017 06:51:37 +0200 Subject: Getting Input From User In-Reply-To: <194CA109-893A-459A-A757-AE3D0FB4245B@oracle.com> References: <6D7BA1EC-F4EE-415D-B280-F57265F4A452@oracle.com> <194CA109-893A-459A-A757-AE3D0FB4245B@oracle.com> Message-ID: That expanded my horizon, thank you. However even though print() utilizes the given writer, E.G: Socket's OutputWriter, readLine still uses the System.in even though I use engine.getContext().setReader(InputStreamReader of a Socket). Would that be some kind of bug? Because that makes Scriptcontext.setReader() method kind of useless. Burak On 2/25/17, James Laskey wrote: > You have to be in scripting mode to to use those functions. > https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/shell.html. > It's possible to add command line options when using from java. > https://wiki.openjdk.java.net/display/Nashorn/Nashorn+jsr223+engine+notes > > -- Jim > > Sent from my iPhone > >> On Feb 25, 2017, at 1:41 PM, Koray wrote: >> >> This is exactly what I'm looking for. Is it possible to do this from >> inside a Java application? I have tried readLine() and readFully() >> methods before, but I'm guessing they are meant for the commandline >> tool only. >> >> Burak >> On 2/25/17, Jim Laskey (Oracle) wrote: >>>>> jjs -scripting >>> jjs> var name = readLine("Your name >> "); >>> Your name >> Jim >>> jjs> print(name) >>> Jim >>> >>> That sort of thing? >>> >>> ? Jim >>> >>> >>>> On Feb 25, 2017, at 5:24 AM, Koray wrote: >>>> >>>> Hello, >>>> >>>> I apologize if this is not the place to ask, but I couldn't get a >>>> satisfying answer from anywhere else so this is kind of my last >>>> resort. >>>> >>>> Is there any built-in function to get input from a user when using >>>> NashornScriptEngine? print() method allows us to utilize both the >>>> default OutputStreamWriter (System.out) and any writers that we set >>>> using ScriptContext, but how can I make use of the reader which is >>>> used by the engine? >>>> >>>> Thank you, >>>> Burak >>> >>> >> >> >> -- >> sayg?lar?mla >> Burak Koray Polat > -- sayg?lar?mla Burak Koray Polat From sundararajan.athijegannathan at oracle.com Mon Feb 27 01:38:04 2017 From: sundararajan.athijegannathan at oracle.com (Sundararajan Athijegannathan) Date: Mon, 27 Feb 2017 07:08:04 +0530 Subject: Getting Input From User In-Reply-To: References: <6D7BA1EC-F4EE-415D-B280-F57265F4A452@oracle.com> <194CA109-893A-459A-A757-AE3D0FB4245B@oracle.com> Message-ID: <58B382FC.5040603@oracle.com> I think print and readLine cannot be compared. Differences: * print is always available. Both in -scripting mode as well as normal mode. * readLine extension (as Jim pointed out) is available only in -scripting mode. (scripting mode is meant "shell" style scripting with nashorn) * While it is usually okay/safe to use arbitrary output/print stream and direct output there, read/readLine is expected read from console (meant for interactive user input). That said, it should be straightforward to define your own read/readLine replacement function that uses ScriptContext's Reader. -Sundar On 26/02/17, 10:21 AM, Koray wrote: > That expanded my horizon, thank you. > > However even though print() utilizes the given writer, E.G: Socket's > OutputWriter, readLine still uses the System.in even though I use > engine.getContext().setReader(InputStreamReader of a Socket). Would > that be some kind of bug? Because that makes Scriptcontext.setReader() > method kind of useless. > > Burak > On 2/25/17, James Laskey wrote: >> You have to be in scripting mode to to use those functions. >> https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/shell.html. >> It's possible to add command line options when using from java. >> https://wiki.openjdk.java.net/display/Nashorn/Nashorn+jsr223+engine+notes >> >> -- Jim >> >> Sent from my iPhone >> >>> On Feb 25, 2017, at 1:41 PM, Koray wrote: >>> >>> This is exactly what I'm looking for. Is it possible to do this from >>> inside a Java application? I have tried readLine() and readFully() >>> methods before, but I'm guessing they are meant for the commandline >>> tool only. >>> >>> Burak >>> On 2/25/17, Jim Laskey (Oracle) wrote: >>>>>> jjs -scripting >>>> jjs> var name = readLine("Your name>> "); >>>> Your name>> Jim >>>> jjs> print(name) >>>> Jim >>>> >>>> That sort of thing? >>>> >>>> ? Jim >>>> >>>> >>>>> On Feb 25, 2017, at 5:24 AM, Koray wrote: >>>>> >>>>> Hello, >>>>> >>>>> I apologize if this is not the place to ask, but I couldn't get a >>>>> satisfying answer from anywhere else so this is kind of my last >>>>> resort. >>>>> >>>>> Is there any built-in function to get input from a user when using >>>>> NashornScriptEngine? print() method allows us to utilize both the >>>>> default OutputStreamWriter (System.out) and any writers that we set >>>>> using ScriptContext, but how can I make use of the reader which is >>>>> used by the engine? >>>>> >>>>> Thank you, >>>>> Burak >>>> >>> >>> -- >>> sayg?lar?mla >>> Burak Koray Polat > From burakkoray at gmail.com Mon Feb 27 09:51:12 2017 From: burakkoray at gmail.com (Koray) Date: Mon, 27 Feb 2017 11:51:12 +0200 Subject: Getting Input From User In-Reply-To: <58B382FC.5040603@oracle.com> References: <6D7BA1EC-F4EE-415D-B280-F57265F4A452@oracle.com> <194CA109-893A-459A-A757-AE3D0FB4245B@oracle.com> <58B382FC.5040603@oracle.com> Message-ID: That is true. Writing a function was always an option, but ScriptContext's setReader(Reader) method made me think that there would be a way to use it like the writer. But I guess it all makes sense now. Thanks to both of you for your help. Burak On 2/27/17, Sundararajan Athijegannathan wrote: > I think print and readLine cannot be compared. > > Differences: > > * print is always available. Both in -scripting mode as well as normal > mode. > * readLine extension (as Jim pointed out) is available only in > -scripting mode. (scripting mode is meant "shell" style scripting with > nashorn) > * While it is usually okay/safe to use arbitrary output/print stream and > direct output there, read/readLine is expected read from console (meant > for interactive user input). > > That said, it should be straightforward to define your own read/readLine > replacement function that uses ScriptContext's Reader. > > -Sundar > > On 26/02/17, 10:21 AM, Koray wrote: >> That expanded my horizon, thank you. >> >> However even though print() utilizes the given writer, E.G: Socket's >> OutputWriter, readLine still uses the System.in even though I use >> engine.getContext().setReader(InputStreamReader of a Socket). Would >> that be some kind of bug? Because that makes Scriptcontext.setReader() >> method kind of useless. >> >> Burak >> On 2/25/17, James Laskey wrote: >>> You have to be in scripting mode to to use those functions. >>> https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/shell.html. >>> It's possible to add command line options when using from java. >>> https://wiki.openjdk.java.net/display/Nashorn/Nashorn+jsr223+engine+notes >>> >>> -- Jim >>> >>> Sent from my iPhone >>> >>>> On Feb 25, 2017, at 1:41 PM, Koray wrote: >>>> >>>> This is exactly what I'm looking for. Is it possible to do this from >>>> inside a Java application? I have tried readLine() and readFully() >>>> methods before, but I'm guessing they are meant for the commandline >>>> tool only. >>>> >>>> Burak >>>> On 2/25/17, Jim Laskey (Oracle) wrote: >>>>>>> jjs -scripting >>>>> jjs> var name = readLine("Your name>> "); >>>>> Your name>> Jim >>>>> jjs> print(name) >>>>> Jim >>>>> >>>>> That sort of thing? >>>>> >>>>> ? Jim >>>>> >>>>> >>>>>> On Feb 25, 2017, at 5:24 AM, Koray wrote: >>>>>> >>>>>> Hello, >>>>>> >>>>>> I apologize if this is not the place to ask, but I couldn't get a >>>>>> satisfying answer from anywhere else so this is kind of my last >>>>>> resort. >>>>>> >>>>>> Is there any built-in function to get input from a user when using >>>>>> NashornScriptEngine? print() method allows us to utilize both the >>>>>> default OutputStreamWriter (System.out) and any writers that we set >>>>>> using ScriptContext, but how can I make use of the reader which is >>>>>> used by the engine? >>>>>> >>>>>> Thank you, >>>>>> Burak >>>>> >>>> >>>> -- >>>> sayg?lar?mla >>>> Burak Koray Polat >> > -- sayg?lar?mla Burak Koray Polat From Joerg.Frantzius at aperto.com Mon Feb 27 11:58:30 2017 From: Joerg.Frantzius at aperto.com (=?utf-8?B?RnJhbnR6aXVzLCBKw7ZyZw==?=) Date: Mon, 27 Feb 2017 11:58:30 +0000 Subject: Efficiency of context-per-thread on shared engine vs. engine + context per thread? Message-ID: <4DDDC5EC-6DDA-4FDD-9BE8-2C89777F1F8F@aperto.com> Hi, for our application we?re about to implement a global-per-thread on single engine approach, and I?d be very thankful if someone in the know could share some insights on whether this is worth the effort when compared to engine-per thread (as the latter seems much more easy to implement for us). More precisely the question is whether a single engine with multiple ScriptContexts is substantially more resource-efficient than multiple engines (each with their own ScriptContext)? Does Nashorn e.g. share code-optimization between engines? Or does it share code-optimization between ScriptContexts on a single engine in the first place? Also it would be great to know about the memory-footprint of the engine, e.g. http://stackoverflow.com/questions/24116672/how-much-memory-does-a-nashorn-scriptengine-use seems to say that an empty engine is ~324KB, but I?d expect that to be higher when it is actually executing code. Thanks for any insights + regards, J?rg --- Dipl. Inf. J?rg von Frantzius, Technical Director E-Mail joerg.frantzius at aperto.com Phone +49 30 283921-318 Fax +49 30 283921-29 Aperto GmbH ? An IBM Company Chausseestra?e 5, D-10115 Berlin http://www.aperto.com http://www.facebook.com/aperto https://www.xing.com/companies/apertoag HRB 77049 B, AG Berlin Charlottenburg Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel Simon From james.laskey at oracle.com Mon Feb 27 12:14:30 2017 From: james.laskey at oracle.com (Jim Laskey (Oracle)) Date: Mon, 27 Feb 2017 08:14:30 -0400 Subject: Efficiency of context-per-thread on shared engine vs. engine + context per thread? In-Reply-To: <4DDDC5EC-6DDA-4FDD-9BE8-2C89777F1F8F@aperto.com> References: <4DDDC5EC-6DDA-4FDD-9BE8-2C89777F1F8F@aperto.com> Message-ID: From basic experience I found that using a single engine, using JavaScript code to create the new threads and using loadWithNewGlobal to start each thread gave the best overall performance. - Jim > On Feb 27, 2017, at 7:58 AM, Frantzius, J?rg wrote: > > Hi, > > for our application we?re about to implement a global-per-thread on single engine approach, and I?d be very thankful if someone in the know could share some insights on whether this is worth the effort when compared to engine-per thread (as the latter seems much more easy to implement for us). > > More precisely the question is whether a single engine with multiple ScriptContexts is substantially more resource-efficient than multiple engines (each with their own ScriptContext)? Does Nashorn e.g. share code-optimization between engines? Or does it share code-optimization between ScriptContexts on a single engine in the first place? > > Also it would be great to know about the memory-footprint of the engine, e.g. http://stackoverflow.com/questions/24116672/how-much-memory-does-a-nashorn-scriptengine-use seems to say that an empty engine is ~324KB, but I?d expect that to be higher when it is actually executing code. > > Thanks for any insights + regards, > J?rg > > > --- > > Dipl. Inf. J?rg von Frantzius, Technical Director > > E-Mail joerg.frantzius at aperto.com > > Phone +49 30 283921-318 > Fax +49 30 283921-29 > > Aperto GmbH ? An IBM Company > Chausseestra?e 5, D-10115 Berlin > http://www.aperto.com > http://www.facebook.com/aperto > https://www.xing.com/companies/apertoag > > HRB 77049 B, AG Berlin Charlottenburg > Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel Simon > From Joerg.Frantzius at aperto.com Tue Feb 28 21:05:57 2017 From: Joerg.Frantzius at aperto.com (=?utf-8?B?RnJhbnR6aXVzLCBKw7ZyZw==?=) Date: Tue, 28 Feb 2017 21:05:57 +0000 Subject: Object.create() fails on function in SimpleBindings Message-ID: <6498197B-39BB-45E0-87B4-8E91513E9EFB@aperto.com> Hi, in my code I?m running into an issue for which https://github.com/coveo/nashorn-commonjs-modules/issues/3 luckily provides a snippet for reproducing: @Test public void testObjectCreateOnFunction() throws ScriptException { ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); engine.put("foo", engine.eval("function() { return {}; }", new SimpleBindings())); engine.eval("Object.create(foo());"); } This fails with: Caused by: :1 TypeError: [object Object] is not an Object at jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:57) at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:213) at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:185) at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:172) at jdk.nashorn.internal.objects.Global.checkObject(Global.java:2073) at jdk.nashorn.internal.objects.NativeObject.create(NativeObject.java:261) at jdk.nashorn.internal.scripts.Script$21$\^eval\_.:program(:1) at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:623) at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:494) at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393) at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:446) ... 31 more In my own code, the pattern is slightly different, but it fails similarly (SimpleScriptContext internally uses SimpleBindings as well): @Test public void testObjectCreateInFunction() throws ScriptException { ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); SimpleScriptContext context = new SimpleScriptContext(); context.setAttribute("f", engine.eval("(function () {Object.create(this)})"), ScriptContext.ENGINE_SCOPE); engine.eval("f.call({})", context); } The issue seems to be that the function object internally isn?t turned from ScriptObjectMirror into ScriptObject, so Global.checkObject() fails. I?d be thankful for any hints on whether this may be a bug or intended behaviour. Regards, J?rg --- Dipl. Inf. J?rg von Frantzius, Technical Director E-Mail joerg.frantzius at aperto.com Phone +49 30 283921-318 Fax +49 30 283921-29 Aperto GmbH ? An IBM Company Chausseestra?e 5, D-10115 Berlin http://www.aperto.com http://www.facebook.com/aperto https://www.xing.com/companies/apertoag HRB 77049 B, AG Berlin Charlottenburg Gesch?ftsf?hrer: Dirk Buddensiek, Kai Gro?mann, Stephan Haagen, Daniel Simon