我有一个可行的解决方案,但这显然是一个hack。
测试程序:
public class Nashorn { public static void main(String[] args) throws scriptException { scriptEngine engine = new scriptEngineManager().getEngineByName("nashorn"); Map<String, Object> map = new HashMap<>(); map.put("a", 10); map.put("b", 20); try (GlobalMap globals = new GlobalMap(map)) { engine.eval("c = a + b; a += b;", globals); } System.out.println("map = " + map); }}测试程序
map = {a=30.0, b=20, c=30.0}根据需要输出。GlobalMap截取项将拦截Nashorn全局对象在key下的
"nashorn.global"存储,因此不会将其存储在地图中。当
GlobalMap关闭时,它会从原地图的犀牛全局对象,并将它们存储任何新的全局变量:
public class GlobalMap extends SimpleBindings implements Closeable { private final static String NASHORN_GLOBAL = "nashorn.global"; private Bindings global; private Set<String> original_keys; public GlobalMap(Map<String, Object> map) { super(map); } @Override public Object put(String key, Object value) { if (key.equals(NASHORN_GLOBAL) && value instanceof Bindings) { global = (Bindings) value; original_keys = new HashSet<>(global.keySet()); return null; } return super.put(key, value); } @Override public Object get(Object key) { return key.equals(NASHORN_GLOBAL) ? global : super.get(key); } @Override public void close() { if (global != null) { Set<String> keys = new HashSet<>(global.keySet()); keys.removeAll(original_keys); for (String key : keys) put(key, global.remove(key)); } }}我仍然希望找到一种解决方案,将当前范围设置为
Map<String,Object>或
Bindings对象,并将脚本创建的任何新变量直接存储在该对象中。



