The issue is that with an AST/analyzing approach you have to severely limit the functionality you expose to the scripter, to guarantee it to run within finite resources. With ASM/rewriting you can analyze the behaviour of the script at runtime, halting/interrupting the script when you deem it appropriate, while retaining all features that should reasonably be available to the scripter.
That’s all, folks, because ‘Pfffff…’ is a tad hard to expand upon
I don’t see the basis of this statement (hence the Pffff)…anything you can do in one you can do in the other. The disadvantage of ASM is that you’ve already thrown away high-level structure information and you’re working with lower level constructions.
If only Java had some sort of resource management thing built in to it to manage allocation of system resources… and application segregation. Then you could just say, “you’re allowed n files open, n megabytes in a heap of your own, n threads running at NORM_PRIORITY-1 or less, which are each allowed to run for n seconds before they’re forcibly terminated” and that sort of thing.
That’s the core of our miscommunication. You argue that within all the restrictions you impose, both solutions are equal. That is correct, but my solution doesn’t require these restrictions.
To extrapolate your solution: if you minimize the exposed functionality to nothing, nothing bad can happen.
To extrapolate my solution: if you validate every execution of each instruction, nothing bad can happen.
For a general purpose solution, I’d pick the solution imposing the least amount of restrictions, as it directly affects the way you can express ideas through code, and therefore productivity.
Hi,
I finally got ASM working after a lot of reading about how JVM byte codes and ClassLoaders work.
I made some code that reads an existing class’s byte codes, modifies the byte code by adding some extra characters onto a String field within the class’s method’s body, then calls that method and prints the String returned which shows that the byte code changes worked and the String is different to the original. If anyone wants to mess with it, here it is: https://dl.dropboxusercontent.com/u/50479250/ASMTest.zip
Thanks for pointing out the opcodes that I should look into Riven:
I don’t understand bytecodes and compilers well enough yet, but once I’ve read some more about these I’ll probably have a few questions about how to calculate the amount of memory being allocated with each opcode, and how to chase the allocations made in other objects’ methods if they’re called.
I’m really looking forward to seeing this working. It’ll be cool to have safe and secure client-programmable scripts that run on the server. Once the code’s reasonably secure, I’ll host a web page where we can upload and execute malicious java code on the server to see if these methods are effective
@Riven: Neither of us are currently discussing difficult transforms, so the choice between bytecode vs. AST manipulation is not important if your equally familiar with both. Otherwise it’s what you’ve more experience with and for people with none in either I’d expect AST to be easier. YMMV.
On the array allocation example for instance (since I provided no details) I don’t see that replacing the length expression with a wrapped expression (really an rvalue) is impossibly difficult…it’s the same difficulty as adding a dup and a method call as far as I’m concerned. But enough of that subject.
My suggestion is to provide DSL/Scripting functionality to scripters rather than general purpose programming constructs which are potentially problematic for running on a server. Let’s keep in mind that people that end up scripting stuff for games frequently have little to no programming experience (not that I’m suggesting to cater to these folks.) If initially the scripting language itself is too restrictive it’s always possible to attempt to address that at a future point assuming it seems somehow worthwhile. The engineering cost of this solution is low.
Except it not as easy so you’re presenting. You must not allow the engine nor any other classes hold any references to the allocated memory to insure it doesn’t escape the script’s entry point. The tricky part here is the scripter’s own classes via static fields. Additionally you need to track the (rough) amount of memory allocated from script entry and toss an exception if you goes beyond some threshold. Sure this isn’t hard…it simply more up-front work to support a feature a scripter shouldn’t really need in the first place.
EDIT: Oh…and I left out any instance fields of scripter objects which the engine might hold cannot hold a reference to any other scripter object or engine provided container/array.