Using NailGun to defeat JVM startup woes

50 views
Skip to first unread message

Charles Oliver Nutter

unread,
Nov 6, 2007, 10:42:13 PM11/6/07
to
It's become increasingly frustrating that JVM startup is still so much
slower than most command-line programs.

In the JRuby world, we've now managed to convincingly pass the C
implementation of Ruby 1.8 in performance. But even on the fastest
systems, our startup time is a good couple seconds. At its worst, it can
be as high as ten seconds. Our users are very tired of waiting.

http://www.martiansoftware.com/nailgun/index.html

Nailgun is a project that appears to be mostly dead since 2005, but it
basically provides a simple "JVM server" on one end and a native client
on the other. You call ng like you'd call java, with a class and
arguments it should be passed. And it sends that class and arguments
across a socket to the ng server, where the class is started up and the
streams are all piped back and forth. When the class terminates, the
client terminates.

Here's a sample of JRuby startup time on OS X Java 6, first normal and
then with ng:

normal:

~/NetBeansProjects/jruby $ time jruby -e "puts 'hello'"
hello

real 0m1.944s
user 0m1.511s
sys 0m0.138s

nailgun:

~/NetBeansProjects/jruby $ time jruby -e "puts 'hello'"
hello

real 0m0.103s
user 0m0.006s
sys 0m0.009s

Obviously it's a substantial improvement.

Now there are a few issues with Nailgun that I've seen so far:

- it doesn't pass along CWD, so if I switch to another directory the
launched class on the remote server doesn't pick that up. Of course the
JVM only has one CWD anyway, but in JRuby we have one per JRuby
runtime...so we could implement our own wrapper around the Nailgun
server that's aware of this. But we'd still need to tweak the native
client to send it across.
- you obviously can't pass JVM flags across the wire, since the JVM is
already started up. This also applies to classpath...but JRuby will
generally use a runtime-dynamic classpath anyway, so that issue is lessened.
- I had some trouble with one Ruby app that uses a readline library; it
didn't appear to pipe correctly. The client needs better term support, I
would guess.

I'm debating trying to get Nailgun running again as a project, so these
issues can be resolved. In the absence of some other miracle, there's
not going to be a better way to get native-like startup times for those
of us implementing languages used heavily for small command-line
utilities. Nailgun seems like a 75% solution that could become something
pretty nice with a little work.

Thoughts on this? Other suggestions for defeating startup woes?

To try it out in JRuby:

1. check out JRuby trunk at http://svn.codehaus.org/jruby/trunk/jruby
1.5. build JRuby with "ant"
2. run 'make' from within bin/nailgun
3. start up a server with jruby-ng-server
4. instead of 'jruby' run 'jruby-ng'. -J options are not passed on.

- Charlie

Charles Oliver Nutter

unread,
Nov 6, 2007, 10:55:43 PM11/6/07
to jvm-la...@googlegroups.com
Charles Oliver Nutter wrote:
> - it doesn't pass along CWD, so if I switch to another directory the
> launched class on the remote server doesn't pick that up. Of course the
> JVM only has one CWD anyway, but in JRuby we have one per JRuby
> runtime...so we could implement our own wrapper around the Nailgun
> server that's aware of this. But we'd still need to tweak the native
> client to send it across.

Actually looking at the NG code I see it does send ENV contents along,
so theoretically CWD is already getting passed. I need to look into
writing a little JRuby wrapper that can get the ENV stuff out.

- Charlie

Daniel Spiewak

unread,
Nov 7, 2007, 12:05:54 AM11/7/07
to JVM Languages
Here's the problem with that: it requires everyone to be using this
"JVM Server" on their machine. JVM langs are so great partially
because they run everywhere there's a JVM (which is practically
everywhere). I can't think of anyone that has nailgun installed. But
even assuming you just packaged Nailgun with the main language distro,
there's still the problem of starting it as a service. Not everyone
is going to *want* to have a persistent JVM instance running in the
background. And chances are, those who do want it know enough to be
concerned about the implications of things like static variables, UI
dispatch thread, etc.

It's a good idea, but practically speaking I don't think it's a good
candidate for JVM lang startup improvements.

My personal thought for defeating startup woes has always been that we
should focus on loading as narrow a scope as possible. Obviously the
client JVM has a minimum start time that simply can't be overcome.
But by asynchronously loading things which are not needed until later
in the execution process, we can pass on the illusion of a fast start
(since it would actually be slower amortized over the first few
seconds of execution).

Honestly I don't even know if a project is already doing this, but I
think it's a thought worth considering. There are innumerable static
analysis techniques for examining code to determine dependencies and
internal requirements on the fly. Given that this sort of analysis
would be running at (or immediately before) the actual execution of
the code, we would actually have a valid runtime environment to work
with. Thus, in all but some very odd cases, the dynamic nature of
languages like Ruby, Groovy, Python and so on wouldn't pose too much
of an issue. The idea being, until the whole environment is
completely loaded and initialized, only load things bit-by-bit as
required to execute the code *right now*. For implementations which
support JITing (like JRuby and Groovy), this would be the last thing
loaded and more-or-less disabled until the entire environment is
available.

Anyway, I'm a bit out of my field of expertise, so I'll admit I don't
even know if this has been considered before, or simply rejected
immediately due to its complete lunacy. :-) Just thought I'd put it
on the table.

Daniel

On Nov 6, 9:42 pm, Charles Oliver Nutter <charles.nut...@sun.com>
wrote:

> 1. check out JRuby trunk athttp://svn.codehaus.org/jruby/trunk/jruby

Charles Oliver Nutter

unread,
Nov 7, 2007, 12:41:58 AM11/7/07
to jvm-la...@googlegroups.com
Daniel Spiewak wrote:
> Here's the problem with that: it requires everyone to be using this
> "JVM Server" on their machine. JVM langs are so great partially
> because they run everywhere there's a JVM (which is practically
> everywhere). I can't think of anyone that has nailgun installed. But
> even assuming you just packaged Nailgun with the main language distro,
> there's still the problem of starting it as a service. Not everyone
> is going to *want* to have a persistent JVM instance running in the
> background. And chances are, those who do want it know enough to be
> concerned about the implications of things like static variables, UI
> dispatch thread, etc.

This isn't something that would be spun up for all users. The normal
"jruby" command would continue to start a whole JVM. But I've got
Nailgun committed to JRuby now as a second option:

bin/jruby-ng-server
bin/jruby-ng

If you want to use the server, say if you're going to be running a lot
of command-line tools, just spin it up in the background somewhere.

jruby-ng-server > /dev/null 2> /dev/null &

And then use the jruby-ng command instead, or alias it to "jruby"

alias jruby=jruby-ng

jruby -e "puts 'here'"

The idea is that users will have a new option to try. For JRuby, where
we have no global variables, no dependencies on static fields, and
already depend on our ability to spin up many JRuby instances in a
single JVM, this ends up working very well. It's building off features
we already provide, and giving users the benefit of a fast,
pre-initialized JVM without the startup hit.

I think we're probably going to ship with this for JRuby 1.1 now. It's
working really well. I've managed to resolve the CWD issue by defining
my own "nailMain" next to our existing "main", and ENV vars are being
passed along as well. The one big remaining complication I don't have an
answer for just yet is OS signals; they get registered only in the
server process, so signals from the client don't propagate through. It's
fixable of course, by having the client register and the server just
listen for client signal events, but that isn't supported in the current
NG. So there's some work to do.

All the NG stuff is in JRuby trunk right now. Give it a shot.

- Charlie

Patrick Wright

unread,
Nov 7, 2007, 3:14:27 AM11/7/07
to jvm-la...@googlegroups.com
Hi Charles

I've used Nailgun on a few different projects. Generally, I think it
rocks, but a Nailgun 2.0 would be welcome to address open issues.

First, I've used NG for
1) hosting a small image converter utility which I used to convert a
large number of image files for some documentation I was writing. The
utility was written in Java; Hotspot optimizations sped the process up
considerably because the utility remained loaded in NG
2) running BeanShell scripts to write a client for a complex JEE app
3) writing a CLI for developers to easily create data using our
standard, multi-layered libraries, where the cost of initializing
those libraries was absorbed once, on first execution
4) experimental--to run scala programs (they already have an optional
memory-resident compiler, fsc)

Some issues
1) I'm not sure that NG apps respond correctly to interrupts, e.g. if
the process being launched is long-running, I think that an interrupt
(ctrl-c) won't stop the NG process (and there would be no way to
automatically do so, without an interruption API). I thought I saw
this behavior recently (most of the apps I've used with NG have not
been long-running, till now)--have you tested this?
2) NG server is not secure (Marty says as much). It listens over some
port and accepts any requests that come over the network, regardless.
Best practice would include, at a minimum, always using a standard
port which is firewalled to prevent external (non-host) access.
3) NG doesn't really have a way to tell you what version of anything
you are currently running; there isn't really a deployment model--you
can just execute some class that is on the classpath available to NG.
If you have a long-running NG server process, I've found this could be
confusing (e.g. older versions of classes being used instead of my new
ones). For scripts/interpreters this may be less of an issue.

Some ideas for further work:
1) The basic idea is very cool, but I'd suggest that a fast compiled
language other than C, for example Python-C, may be a better
alternative. It would probably make the NG client more clear to read,
extend, and verify.
2) For the server, it might make more sense to use a lightweight
pluggable-protocol-based server like Mina, or an app server running in
"microkernel" mode, like Glassfish. That would give us a model for
deployment, monitoring, dispatching, etc. For the most part that would
mean porting the protocol handler to the target server--which might
give us a secondard advantage of supporting multiple different servers
instead of just the NG server.

I've pushed NG quite a bit over the years to friends and in discussion
groups. It's nice to see you over at jRuby taking an interest in it.
It's a useful little tool, and probably of immediate use to any of the
JVM languages on this list, in particular those with an interpreter.
With that in mind, it might be a good idea for a tool to include in
the JVM Languages Runtime toolchest (or include some variation on the
same idea).


Regards
Patrick

Charles Oliver Nutter

unread,
Nov 7, 2007, 9:48:04 AM11/7/07
to jvm-la...@googlegroups.com
Patrick Wright wrote:
> Some issues
> 1) I'm not sure that NG apps respond correctly to interrupts, e.g. if
> the process being launched is long-running, I think that an interrupt
> (ctrl-c) won't stop the NG process (and there would be no way to
> automatically do so, without an interruption API). I thought I saw
> this behavior recently (most of the apps I've used with NG have not
> been long-running, till now)--have you tested this?

This is the signal issue I mentioned. I don't believe it would be too
difficult to push signal handling to the client and pass events across
the wire to the server process. Interruption would be a problem,
especially since just killing the remote JVM would be unacceptable, but
JRuby already has mechanisms in place for terminating a running Ruby
app/script that we would hook into. And ultimately, it's just a matter
of being clever on the server with your Nails...but that's impossible to
do right now without signals coming over the wired.

> 2) NG server is not secure (Marty says as much). It listens over some
> port and accepts any requests that come over the network, regardless.
> Best practice would include, at a minimum, always using a standard
> port which is firewalled to prevent external (non-host) access.

Yeah, I wouldn't expect NG would be something people would start up and
leave running for long periods of time. I'd expect it's something you
start up (or something that comes up with your IDE of choice, maybe?),
that listens only on loopback, and that you shut down when you're
through working. Maybe a more secure NG would be needed for some
applications, but I think making NG rock-solid (signals, etc) first
would be my priority.

> 3) NG doesn't really have a way to tell you what version of anything
> you are currently running; there isn't really a deployment model--you
> can just execute some class that is on the classpath available to NG.
> If you have a long-running NG server process, I've found this could be
> confusing (e.g. older versions of classes being used instead of my new
> ones). For scripts/interpreters this may be less of an issue.

Definitely less of an issue here; people will not be monkeying with
JRuby version. One thing that would need to be improved, however, is
adding the ability to pass along the client CLASSPATH and set up a child
classloader for every Nail based on that CP. That shouldn't be too
difficult; you just make sure to start up the server with a
minimal/default CP, and then the additional CP gets tacked on for every
Nail. And this too is largely already possible, since it's sending along
env vars, but I'm not sure whether NG is using separate classloaders yet.

> Some ideas for further work:
> 1) The basic idea is very cool, but I'd suggest that a fast compiled
> language other than C, for example Python-C, may be a better
> alternative. It would probably make the NG client more clear to read,
> extend, and verify.

Not a bad thought, but I'm not sure the requirement to have a C-based
scripting language installed is much better than requiring a compiler be
installed as is the case now. In our case, we can't even count on Ruby
being present; there are *lots* of people who have explicitly requested
that JRuby never require Ruby be installed.

It would certainly be more maintainable though. If only there weren't
that "other" OS that comes with no common scripting languages installed,
we wouldn't have to think about this one so much.

> 2) For the server, it might make more sense to use a lightweight
> pluggable-protocol-based server like Mina, or an app server running in
> "microkernel" mode, like Glassfish. That would give us a model for
> deployment, monitoring, dispatching, etc. For the most part that would
> mean porting the protocol handler to the target server--which might
> give us a secondard advantage of supporting multiple different servers
> instead of just the NG server.

That's actually a good idea...as long as that server could be really
minimal. Every app server I know of takes at least 50M of its own memory
before even starting up your app, where my little JRuby NG server starts
up in about 25M. But the manageability, security, and reliability of a
real app server would probably outweigh the costs, and a fast network
engine like Grizzly could help apps that are going to crank out a lot of
content.

GlassFish would be my choice for this; for the experimental
GlassFish-Rails "gem" they've managed to strip it down to a few MB,
which is really impressive, and the GlassFish v3 kernel is widely touted
as being only a few hundred kb.

> I've pushed NG quite a bit over the years to friends and in discussion
> groups. It's nice to see you over at jRuby taking an interest in it.
> It's a useful little tool, and probably of immediate use to any of the
> JVM languages on this list, in particular those with an interpreter.
> With that in mind, it might be a good idea for a tool to include in
> the JVM Languages Runtime toolchest (or include some variation on the
> same idea).

I agree. Have you ever communicated with the folks behind NG? I'd rather
not fork it, but I'm not getting responses to any emails I send to their
mailing list, and the whole of Martian Software Inc appears to have gone
quiet since late 2006.

- Charlie

Neil Bartlett

unread,
Nov 7, 2007, 10:28:07 AM11/7/07
to jvm-la...@googlegroups.com
Charles,

If modular microkernels like the one in GlassFish are of interest,
then you might also want to take a look at OSGi. It is compact, like
GlassFish's HK2 (in fact the mandatory core of OSGi has less classes
than HK2), is substantially more battle-tested, and has three open-
source implementations.

However in any NailGun-like server, security is surely a major
concern. What we need is a runtime that can execute transmitted
bytecode in a secure sandbox, while allowing some code to break out of
the sandbox based on certain guarantees such as code signing.

Is it just me, or does this sound exactly like Applets?

Neil

Patrick Wright

unread,
Nov 7, 2007, 10:37:21 AM11/7/07
to jvm-la...@googlegroups.com
> This is the signal issue I mentioned. I don't believe it would be too
> difficult to push signal handling to the client and pass events across
> the wire to the server process. Interruption would be a problem,
> especially since just killing the remote JVM would be unacceptable, but
> JRuby already has mechanisms in place for terminating a running Ruby
> app/script that we would hook into. And ultimately, it's just a matter
> of being clever on the server with your Nails...but that's impossible to
> do right now without signals coming over the wired.

I think I would have three stages (depending on how much integration
you want in the NG server):
- plain JVM class - main() gets called; NG default
- JVM class with nailMain()
- JVM class implementing some interface - interface could include
signalledStop()


> Yeah, I wouldn't expect NG would be something people would start up and
> leave running for long periods of time. I'd expect it's something you
> start up (or something that comes up with your IDE of choice, maybe?),
> that listens only on loopback, and that you shut down when you're
> through working. Maybe a more secure NG would be needed for some
> applications, but I think making NG rock-solid (signals, etc) first
> would be my priority.

It is something I would advertise, though; it seems irresponsible not
to. I do imagine developers may leave this running in the background
(assume it can stay up for many hours, which in my experience is
true).


> Definitely less of an issue here; people will not be monkeying with
> JRuby version. One thing that would need to be improved, however, is

Yes, for a compiler or interpreter it's less of a problem, as long as
the interpreter is checking for file modifications. It's just
something that's bitten me in the past.

> adding the ability to pass along the client CLASSPATH and set up a child
> classloader for every Nail based on that CP. That shouldn't be too
> difficult; you just make sure to start up the server with a
> minimal/default CP, and then the additional CP gets tacked on for every
> Nail. And this too is largely already possible, since it's sending along
> env vars, but I'm not sure whether NG is using separate classloaders yet.

Sounds like a good feature.


> Not a bad thought, but I'm not sure the requirement to have a C-based
> scripting language installed is much better than requiring a compiler be
> installed as is the case now. In our case, we can't even count on Ruby
> being present; there are *lots* of people who have explicitly requested
> that JRuby never require Ruby be installed.

Actually, I was thinking of compiled Python, to avoid maintaining the
ng.c file in case it needs to be extended. The deliverable/installable
would still be a binary, just what would be maintained is something in
Python.


> That's actually a good idea...as long as that server could be really
> minimal. Every app server I know of takes at least 50M of its own memory
> before even starting up your app, where my little JRuby NG server starts
> up in about 25M. But the manageability, security, and reliability of a
> real app server would probably outweigh the costs, and a fast network
> engine like Grizzly could help apps that are going to crank out a lot of
> content.

Ideally we could move code between containers, NG being the simplest
form of the container. I'm not married to the idea, just that Marty
wrote a bunch of code that's already handled, for other reasons, in
these app servers. The real meat of NG is the client and the simple
protocol, IMO. Of course, having a small server available is also
cool.


> GlassFish would be my choice for this; for the experimental
> GlassFish-Rails "gem" they've managed to strip it down to a few MB,
> which is really impressive, and the GlassFish v3 kernel is widely touted
> as being only a few hundred kb.

Yes, it's also received a redesign in the recent past, which in this
case I think is a plus.

> I agree. Have you ever communicated with the folks behind NG? I'd rather
> not fork it, but I'm not getting responses to any emails I send to their
> mailing list, and the whole of Martian Software Inc appears to have gone
> quiet since late 2006.

Yeah, a couple of years ago (2004?) when Marty was still actively
working on it. Those older mailing lists appear to be gone, not sure
if they were previously hosted on Sourceforge or on Marty's website.

I can't see any reason not to fork (or rather, pick up where he left
off) since it's been out of active development for over two years, and
never moved past version 0.7. Seems to me that starting with NG and
focusing on specific features important to JVM language writers
(including many on this list) would help the tool grow in new and
useful ways. Most JVM languages, esp. those with an interpreter, would
get a boost (was my experience with BSH, for example).

Note that the Scala folks also have a server-based compiler called
FSC; might be interesting to see if there's any overlap there.


Patrick

Patrick Wright

unread,
Nov 7, 2007, 10:42:37 AM11/7/07
to jvm-la...@googlegroups.com
Neil

> However in any NailGun-like server, security is surely a major
> concern. What we need is a runtime that can execute transmitted
> bytecode in a secure sandbox, while allowing some code to break out of
> the sandbox based on certain guarantees such as code signing.
>
> Is it just me, or does this sound exactly like Applets?

It's a different case, although they are complementary. NG takes a
command line request (target class, all parameters, environment) and
pushes it via socket up to a server; the server responds and the
client puts the server output back into the standard sinks (stdout,
stderr). There is no bytecode moving around. In my case, for example,
I was running things like

ng ImageConvert /images -from bmp -to jpg -compression 5

or whatever. It's just like starting a Java class using java.exe but
the class, and dependent classes, are already loaded and possibly
compiled or inlined or whatever.

The security concern is valid, but I think Charles is correct that
listening on loopback is probably good enough for most developers. I
don't know of any exploits that anyone worked out, as you need to know
that the target NG server has some class available with a main() you
can execute. That would exclude most? all? of the JRE. NG itself
doesn't accept bytecode or scripts or anything like that.

OTOH, OSGi always sounds interesting.

Regards
Patrick

Jochen Theodorou

unread,
Nov 7, 2007, 10:56:29 AM11/7/07
to jvm-la...@googlegroups.com
Charles Oliver Nutter schrieb:
[...]

>> 2) NG server is not secure (Marty says as much). It listens over some
>> port and accepts any requests that come over the network, regardless.
>> Best practice would include, at a minimum, always using a standard
>> port which is firewalled to prevent external (non-host) access.
>
> Yeah, I wouldn't expect NG would be something people would start up and
> leave running for long periods of time. I'd expect it's something you
> start up (or something that comes up with your IDE of choice, maybe?),
> that listens only on loopback, and that you shut down when you're
> through working. Maybe a more secure NG would be needed for some
> applications, but I think making NG rock-solid (signals, etc) first
> would be my priority.

XServer shows us how to do that in a multiuser environment.

bye blackdrag

--
Jochen "blackdrag" Theodorou
The Groovy Project Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/
http://www.g2one.com/

Jochen Theodorou

unread,
Nov 7, 2007, 11:03:47 AM11/7/07
to jvm-la...@googlegroups.com
Patrick Wright schrieb:
[...]

> The security concern is valid, but I think Charles is correct that
> listening on loopback is probably good enough for most developers.

That changes very soon when running such an application with root
rights! It would be careless to not to address this. It might be enough
for Windows, but on a Unix like system it is really different. And I
don't know about you, but I do use scripting languages on the command
line more in a Unix-like environment.

> I
> don't know of any exploits that anyone worked out, as you need to know
> that the target NG server has some class available with a main() you
> can execute. That would exclude most? all? of the JRE. NG itself
> doesn't accept bytecode or scripts or anything like that.

what rights is NG using when I write/read a file? If it is the rights
given by the server, because the server process is doing that, then it
can't never be run as root, unless you want grant any normal user access
to anything on the file system. It would be also interesting what NG
shows for properties set by the JVM like user.home

Patrick Wright

unread,
Nov 7, 2007, 11:14:00 AM11/7/07
to jvm-la...@googlegroups.com
> That changes very soon when running such an application with root
> rights! It would be careless to not to address this. It might be enough
> for Windows, but on a Unix like system it is really different. And I
> don't know about you, but I do use scripting languages on the command
> line more in a Unix-like environment.

Yes, I know. I was trying to compromise and come closer to Charles'
position on the topic :).

It is a big drawback of the design. One reason it might be good to run
it in a webapp container, where people already understand what the
issues are, and are used to configuring it for secure access (in his
defense, Marty pointed this problem out quite clearly).


> what rights is NG using when I write/read a file? If it is the rights
> given by the server, because the server process is doing that, then it
> can't never be run as root, unless you want grant any normal user access
> to anything on the file system. It would be also interesting what NG
> shows for properties set by the JVM like user.home

It shouldn't be launched as root, that is true.

It's a topic that needs to be addressed.


Patrick

Jochen Theodorou

unread,
Nov 7, 2007, 11:22:34 AM11/7/07
to jvm-la...@googlegroups.com
Daniel Spiewak schrieb:

> Here's the problem with that: it requires everyone to be using this
> "JVM Server" on their machine. JVM langs are so great partially
> because they run everywhere there's a JVM (which is practically
> everywhere). I can't think of anyone that has nailgun installed. But
> even assuming you just packaged Nailgun with the main language distro,
> there's still the problem of starting it as a service. Not everyone
> is going to *want* to have a persistent JVM instance running in the
> background. And chances are, those who do want it know enough to be
> concerned about the implications of things like static variables, UI
> dispatch thread, etc.

if we forgett about UI, static variabels and such... I had a different
thought... let us say I use the myLang command (doesn't exist) to start
an application. let us also say, that the myLang command checks for the
NailGun server, if not started it starts a new one and attaches itself
to that server. If here is already a server running, then it simply
attaches itself to the server. If the myLang command is completed, then
the server stays, but not till the end of time, let us say just for
another minute or so. If in that time no other myLang command has taken
place, then the server disposes itself from memory. If there is another
myLang command executed during that timeout period, then the server
stays until the new command is completed and starts the waits for the
timeout again.

The advantage are:
* memory is not polluted by a unused resident JVM all the time
* multiple scripts running at the same time can still take advantage of
the server and probably save some memory
* you may get a penalty for the first script startup, but all further
scripts started before the timeout won't have that penalty

I also think that static variables are a solvable problem. The UI
dispatch thread is a bigger problem in my eyes, it would not be very
nice to have one application blocking all UIs.

[...]

> Honestly I don't even know if a project is already doing this, but I
> think it's a thought worth considering. There are innumerable static
> analysis techniques for examining code to determine dependencies and
> internal requirements on the fly. Given that this sort of analysis
> would be running at (or immediately before) the actual execution of
> the code, we would actually have a valid runtime environment to work
> with. Thus, in all but some very odd cases, the dynamic nature of
> languages like Ruby, Groovy, Python and so on wouldn't pose too much
> of an issue. The idea being, until the whole environment is
> completely loaded and initialized, only load things bit-by-bit as
> required to execute the code *right now*. For implementations which
> support JITing (like JRuby and Groovy), this would be the last thing
> loaded and more-or-less disabled until the entire environment is
> available.

ok, then for Groovy... given that the code is not yet compiled Groovy
needs to laod a huge amount of classes for the compiler and for the AST.
Then the code is executed and it needs to load several runtime classes
and needs to create some MetaClasses.... That all happens on demand. If
you have precompiled code, then the compiler won't be loaded unless you
need it somewhen in your code. Groovy does not create a MetaClass for a
class that is not needed. An so on. Maybe something could be done by
splitting some classes, but that won't give a huge amount of speed anymore.

Jochen Theodorou

unread,
Nov 7, 2007, 11:24:20 AM11/7/07
to jvm-la...@googlegroups.com
Patrick Wright schrieb:

>> That changes very soon when running such an application with root
>> rights! It would be careless to not to address this. It might be enough
>> for Windows, but on a Unix like system it is really different. And I
>> don't know about you, but I do use scripting languages on the command
>> line more in a Unix-like environment.
>
> Yes, I know. I was trying to compromise and come closer to Charles'
> position on the topic :).
>
> It is a big drawback of the design. One reason it might be good to run
> it in a webapp container, where people already understand what the
> issues are, and are used to configuring it for secure access (in his
> defense, Marty pointed this problem out quite clearly).

I was more thinking about a per user server.

>> what rights is NG using when I write/read a file? If it is the rights
>> given by the server, because the server process is doing that, then it
>> can't never be run as root, unless you want grant any normal user access
>> to anything on the file system. It would be also interesting what NG
>> shows for properties set by the JVM like user.home
>
> It shouldn't be launched as root, that is true.
>
> It's a topic that needs to be addressed.

even if it is not launched as root... I don't want another user to be
able to write into my home directory ;)

Thomas E Enebo

unread,
Nov 7, 2007, 11:36:19 AM11/7/07
to jvm-la...@googlegroups.com
On Nov 7, 2007 10:24 AM, Jochen Theodorou <blac...@gmx.org> wrote:
>
> Patrick Wright schrieb:
> >> That changes very soon when running such an application with root
> >> rights! It would be careless to not to address this. It might be enough
> >> for Windows, but on a Unix like system it is really different. And I
> >> don't know about you, but I do use scripting languages on the command
> >> line more in a Unix-like environment.
> >
> > Yes, I know. I was trying to compromise and come closer to Charles'
> > position on the topic :).
> >
> > It is a big drawback of the design. One reason it might be good to run
> > it in a webapp container, where people already understand what the
> > issues are, and are used to configuring it for secure access (in his
> > defense, Marty pointed this problem out quite clearly).
>
> I was more thinking about a per user server.
>
> >> what rights is NG using when I write/read a file? If it is the rights
> >> given by the server, because the server process is doing that, then it
> >> can't never be run as root, unless you want grant any normal user access
> >> to anything on the file system. It would be also interesting what NG
> >> shows for properties set by the JVM like user.home
> >
> > It shouldn't be launched as root, that is true.
> >
> > It's a topic that needs to be addressed.
>
> even if it is not launched as root... I don't want another user to be
> able to write into my home directory ;)

Clearly each launched nailgun should only work for the user who
spawned it. A multi-user Nailgun seems like a dangerous Nailgun
(heh). So, it sucks that Java does not support unix domain sockets
(though I am not sure if Windows has equivalent concept). That seems
like it would trivially fix the access issue. I wonder if JNA could
give us enough functionality to hook this up? I personally, would not
mind JNA as a dependency for this feature (JRuby already is using
JNA).

If we cannot use something like Unix Domain sockets then probably a
randomly spawned password by client (which then spawns initial server
instance) which then gets stored securely to a file in users home
directory may do the trick. The successive calls would pass this
secret as proof of ownership. The file that stores the password in
would be chmod'd so other users cannot read it. This file could also
store the pid of the server so we can make sure it did not die at some
point. Combine that with Jochen's spawn on first command logic and
there could be an ENV to main startup lang (jruby) script for people
who don't mind having background server stick around for a while in
case the person will do several invocations in a short period of time.

I guess I am brainstorming, but I suspect we can add or layer
something reasonable onto what exists now...

-Tom

--
Blog: http://www.bloglines.com/blog/ThomasEEnebo
Email: en...@acm.org , tom....@gmail.com

Patrick Wright

unread,
Nov 7, 2007, 11:37:54 AM11/7/07
to jvm-la...@googlegroups.com
> I was more thinking about a per user server.

What exactly is a per-user server? Each user can launch their own
instance on a given box, but ports can't be user-specific, can they?


> even if it is not launched as root... I don't want another user to be
> able to write into my home directory ;)

There will be a number of cases to distinguish. For example, no one
(that I know of) is on my box except for me. If I don't allow incoming
access to a given NG port, then only I (an account on that machine)
can access it. If you are on a box with many users, then you have a
different problem to address.

I don't know of a way to reliably have a user identify/authenticate
themselves to a server, from a command-line, using the sort of
lightweight streaming protocol that NG uses. You might be able to pipe
some sort of key over (a key only your account has rights to read), or
connect over a secure socket, but have to weigh that against the main
goal, which is running things from the command line with low start-up
overhead.


Patrick

Patrick Wright

unread,
Nov 7, 2007, 11:42:47 AM11/7/07
to jvm-la...@googlegroups.com
> If we cannot use something like Unix Domain sockets then probably a
> randomly spawned password by client (which then spawns initial server
> instance) which then gets stored securely to a file in users home
> directory may do the trick. The successive calls would pass this
> secret as proof of ownership. The file that stores the password in
> would be chmod'd so other users cannot read it. This file could also
> store the pid of the server so we can make sure it did not die at some

This (per-launch key) sounds like an improvement over what we have now.

> point. Combine that with Jochen's spawn on first command logic and
> there could be an ENV to main startup lang (jruby) script for people
> who don't mind having background server stick around for a while in
> case the person will do several invocations in a short period of time.

There are different situations I ran into where I wanted the server to
stick around for much longer than a minute or two. One was where the
kinds of operations I was running could take advantage of runtime
optimization, and the other was where the startup process was very
long (long chain of dependencies and injections). Having this be
configurable seems like a plus for me--I can spare the memory more
than the time involved.

Patrick

Szegedi Attila

unread,
Nov 7, 2007, 12:35:43 PM11/7/07
to jvm-la...@googlegroups.com

On 2007.11.07., at 16:28, Neil Bartlett wrote:
>
> However in any NailGun-like server, security is surely a major
> concern. What we need is a runtime that can execute transmitted
> bytecode in a secure sandbox, while allowing some code to break out of
> the sandbox based on certain guarantees such as code signing.
>
> Is it just me, or does this sound exactly like Applets?

Interesting -- my first association was RMI, but you're actually right
too. Applets... who'd have thought we'll be mentioning these in 2007 :-)

Attila.

John Cowan

unread,
Nov 7, 2007, 12:42:26 PM11/7/07
to jvm-la...@googlegroups.com
On 11/7/07, Patrick Wright <pdou...@gmail.com> wrote:

> It shouldn't be launched as root, that is true.

There is no reason at all not to run a root ng-server, provided it
defends itself from requests by non-root users using something like
Tom Enebo's model.

It's important to remember that *every* Unix system is multi-user:
even on a dedicated personal computer, there's always you and root.

If JRuby command-line tools are to be integrated into the regular
command-line ecology, where we don't have to care what language a
program is written in, then I'd expect to run a personal ng-server
from login to logout.

--
GMail doesn't have rotating .sigs, but you can see mine at
http://www.ccil.org/~cowan/signatures

Jochen Theodorou

unread,
Nov 7, 2007, 1:07:48 PM11/7/07
to jvm-la...@googlegroups.com
Patrick Wright schrieb:

>> I was more thinking about a per user server.
>
> What exactly is a per-user server? Each user can launch their own
> instance on a given box, but ports can't be user-specific, can they?

the common technique is to store a file special to the user containing
the port. I think it is a common technique on Unix environments.

>> even if it is not launched as root... I don't want another user to be
>> able to write into my home directory ;)
>
> There will be a number of cases to distinguish. For example, no one
> (that I know of) is on my box except for me. If I don't allow incoming
> access to a given NG port, then only I (an account on that machine)
> can access it. If you are on a box with many users, then you have a
> different problem to address.

that might be right.... but even if you are alone on your box I don't
want to let a nonpriveledged process write into a directory where it
shouldn't write into. Even on Windows these things are becoming more
important since Vista. Every program that opens new security holes on
purpose is to avoid, even if I am alone on my machine, unless you can
guarantee that all other running processes do what they should do and
nothings else. And I don't know about you, but even if I had written all
of them (and at last for the OS I did it surely not) I wouldn't trust my
abilities that much to say that they are all free of bugs and do not
open a backdoor somehow

> I don't know of a way to reliably have a user identify/authenticate
> themselves to a server, from a command-line, using the sort of
> lightweight streaming protocol that NG uses.

that is basically ok, as long as the server has not more rights than the
user.... for example using one server for two user would mean the
server needs to have the rights of both of them, which should not
happen. Another common technique is to give that its own user, for
example the apache is running with its own user. But that is not exactly
what we need, because we still want to for example read/write files of
the user where only the user has the right to read/write them

Jochen Theodorou

unread,
Nov 7, 2007, 1:13:01 PM11/7/07
to jvm-la...@googlegroups.com
John Cowan schrieb:

> On 11/7/07, Patrick Wright <pdou...@gmail.com> wrote:
>
>> It shouldn't be launched as root, that is true.
>
> There is no reason at all not to run a root ng-server, provided it
> defends itself from requests by non-root users using something like
> Tom Enebo's model.

well there is at last the problem that you will need root rights to
start the server. Root rights are to be avoided as much as possible.
that's a general rule. If it is not possible, then there must be a very
good reason for this or no sane administrator will install that software
and a normal user couldn't.

> It's important to remember that *every* Unix system is multi-user:
> even on a dedicated personal computer, there's always you and root.

these are real users, but there are normally much more users than only
these, usually for special processes like the apache server (it is a
user web or apache or something like that, it depends on the distribution).

> If JRuby command-line tools are to be integrated into the regular
> command-line ecology, where we don't have to care what language a
> program is written in, then I'd expect to run a personal ng-server
> from login to logout.

or in other words... give the user complete control and let him start
the server as he likes.

John Cowan

unread,
Nov 7, 2007, 2:58:40 PM11/7/07
to jvm-la...@googlegroups.com
On 11/7/07, Jochen Theodorou <blac...@gmx.org> wrote:

> well there is at last the problem that you will need root rights to
> start the server. Root rights are to be avoided as much as possible.
> that's a general rule. If it is not possible, then there must be a very
> good reason for this or no sane administrator will install that software
> and a normal user couldn't.

I don't mean a multi-user server; I mean multiple instances of the server,
one per user. Thus on my workstation "jcowan" runs one server, which
takes requests only from processes that can prove they are jcowan
by presenting the secret stored in /home/jcowan/.railgun/secret;
"root" runs another server, which correspondingly insists on being
handed the secret from /root/.railgun/secret. Other users that run
processes could have their own servers as needed.

> > If JRuby command-line tools are to be integrated into the regular
> > command-line ecology, where we don't have to care what language a
> > program is written in, then I'd expect to run a personal ng-server
> > from login to logout.
>
> or in other words... give the user complete control and let him start
> the server as he likes.

Sure. I just wanted to debunk the notion that users would typically
keep railgun servers running only briefly.

Charles Oliver Nutter

unread,
Nov 7, 2007, 7:44:22 PM11/7/07
to jvm-la...@googlegroups.com
John Cowan wrote:
> On 11/7/07, Jochen Theodorou <blac...@gmx.org> wrote:
>
>> well there is at last the problem that you will need root rights to
>> start the server. Root rights are to be avoided as much as possible.
>> that's a general rule. If it is not possible, then there must be a very
>> good reason for this or no sane administrator will install that software
>> and a normal user couldn't.
>
> I don't mean a multi-user server; I mean multiple instances of the server,
> one per user. Thus on my workstation "jcowan" runs one server, which
> takes requests only from processes that can prove they are jcowan
> by presenting the secret stored in /home/jcowan/.railgun/secret;
> "root" runs another server, which correspondingly insists on being
> handed the secret from /root/.railgun/secret. Other users that run
> processes could have their own servers as needed.

This is the model I intend for the JRuby Nailgun server; users start up
the server on their own, with their own permissions. And Tom's idea
resolves any possible concerns about other users using your server.

This is NOT intended to be a solution whereby you'd run a single server
for an entire machine over multiple users. There's way too many sticky
issues with that. But having each user run a 25-50MB process when they
log in and piping all their commands through it seems a lot more
efficient than spinning up a 25-50MB process every time they run something.

- Charlie

John Cowan

unread,
Nov 8, 2007, 2:31:37 PM11/8/07
to jvm-la...@googlegroups.com
On Nov 7, 2007 7:44 PM, Charles Oliver Nutter <charles...@sun.com> wrote:

> This is the model I intend for the JRuby Nailgun server; users start up
> the server on their own, with their own permissions.

A nailgun client should note that no server is running and start one
rather than just failing. That fits better with the command-line tools
ecology, where (as I said) you don't want to have to know if a
tool is in JRuby or not.

> But having each user run a 25-50MB process when they
> log in and piping all their commands through it seems a lot more
> efficient than spinning up a 25-50MB process every time they run something.

Indeed, particularly since the server will tend to stay paged out if there is
memory pressure and you aren't using any JRuby commands, so the cost
of running it but not using it is small.

Brian Goetz

unread,
Nov 13, 2007, 2:32:44 PM11/13/07
to jvm-la...@googlegroups.com
Its worth noting that this is very much how Azul's VM works -- they
provide a JVM stub that does little more than act as a server that loads
the class files off the file system and pipes them up to the real VM.
Reply all
Reply to author
Forward
0 new messages