[DGD] Java or LPC (DGD)?

Sampsa Ranta sampsa at netsonic.fi
Sun Aug 17 01:44:21 CEST 2003


Hi,

I've not been in contact with DGD world for a while but I would like to
contribute to your DGD LPC versus Java thread.. =)

Both have been very keen to me, however Java has been my primary language
for a while.

First I must state that I've questioned DGDs minimalistic approach in
past but later on I've come to think it is a good thing. Java basic class
libraries that are in some level ment to be "reference implementation"
are too big for "basic set of tools". And under the hood everything is not
as "smooth" and "sane" as seen on top.

Relevant issues for mudlib:

+ DGD has minimalistic approach for API, with Java there is no "Java for
  Mudlibs"-API yet -> means work!
- Java does not have prebuilt framework like DGD, J2Se has lot of overload

- DGD does not multithread
+ Java multihtreads but one has to use own brains to take control over
  this thing

- J2SE does not have atomic operations and does not give support for
  reloading class bytecode
+ DGD does support atomic code and bytecode reloading

+ Java VM could be used to simulate DGD driver under special Classloader
  and compiler mapping the code to Java bytecode (maybe with proxies or
  direct bytecode to support multible inheritance) but not vice versa.
  DGD driver itself is smart but not too complex features to re-implement
  on as-is base. It seems it has been written under goal like "keep it
  simple". However such simulation would still have to be single threading
  if it is going to be 1:1 simulation.
- DGD cannot simulate Java

- DGD licensing issues, source is open to read and distribute but
  restricted commercial use..
+ Java JVM is free for whatever commercial use also, latest versions
  of "reference implementation" however are not always open and
  nothing forces Sun to keep it open.. However we have GCJ and GNU version
  of class libraries..

+ Java allows fine grained security by security managers howerver
  using these is NOT so well codumented, nothing tells you
  what rights you have to grant to your code in order to make complex
  things work. =)
+ DGD also allows one to protect things within auto object, but as
  Felix fears the networking to cause worms and problems, there is no
  way to connect outside world by what is called the vanilla driver..
  (let's give a hooray for Microsoft RPC here!)

- DGD does not allow persistance/serialization to streams such as the
  network (userobject) directly, only files can be used as primary storage.
+ Java does not have such limitations, serialization does fine with
  streams and there is reflect also if you need to poke around..

+ DGD can precompile LPC to C
+ Java VM usually has JIT and GCJ has ahead-of-time compilation

+ DGD has nice memory management but this requires swapping everything out
  once in a while
- Java/JVM reference implementation has large memory footprint but there
  are alternative implementations and this is not a requirement
  by the language.

Other things not always required for mudlibs:

* DGD is written by one wise fellow, Java is soup of many cooks
  + however the foundation of Java and JVM are well defined
    in "THE JAVA VIRTUAL MACHINE SPECIFICATION" and
    "THE JAVA LANGUAGE SPECIFICATION".
    The J2SE reference implementation is like huge kernel library, one
    could live without most of it using alternative bootstrap code =)
  + DGD code is clean and easy to read

- Extending DGD would require C code that leaves you with out the
  protective care of virtual machine and byte code
+ J2SE has quite extensive and well tested native access library but not
  everything, when you need more than Java can give you, this is no longer
  an issue since you fall back to C =)

+ If a MUD were to implement graphical client, it could be written with
  same language and then there would already be numerous protocols that
  could be easily used for communication (RMI might be useful).
+ DGD is written for as server only and therefore kept simple.

The real issue is how much space time coders have.. DGD might be good
starting point as it is shows how to build manageable persistant stuff
quite easily. If there were wise man to implement same basic behaviour
with Java that would be cool..

If one were to build such thins, it would be recommended to learn from
what Felix has done and how he has done this and compare it to Javas
design approach.

It is nice to see that things were kept and left simple to be extended,
not given as J2SE-size API. One can register management daemons, etc,
but AWT is not basic requirement always..

Of course it would be "required" that you could simply link Java more
stuff afterwards but this should not be built as mandatory requirement for
such kernel, rather as optional.



Comments on the raised technology related issues concerning Java (quite
off topic but whadever)..

--- Reloading issue from Java point of view ---

A Class namespace is defined per Classloader. Same name under same
Classloader should maen same bytecode defining the class. This goes for
sane JVM, of course one could rewrite the JVM and say this is possible,
however would it fit to Java specs is another matter.

Issues raised in this thread on by brief overlook have been well described
in Java specs briefly quoted below.

I assume you are trying to build simulate behavior possible in DGD like
like object management and recompilation, this is doable but not too easy..

First, DGD is able to re-reference an cloned (intance in Java) class
bytecode on flight, Java VM does not give control for this as easily as
kernel library does.

In order to do this in Java, one has first take control over JVM
references control on your own code level and make events such as object
creation and garbage collection visible to the management. Behavior like
this could be done with proxies, this could be done by dynamic proxies
for example BCEL project allows you to do this.
(http://jakarta.apache.org/bcel/index.html)

If proxies were designed smartly, when upgraded, every method call and
response could be rewritten on flight.

You propably would end up having a proxy and Classloader per Class version
but this should be doable.

--- Other things ---

Things like resource limits would be harder to implement and would
require some state of byte code alteration in order to add checks and
analyze cost for an operation. Also blocking operations should be taken in
to account and due to Java's multithreading there would be issues like
synchronization.

Ïf I were to write mudlib in Java, controlling would possibly happen
first hand on thread level.

How ever analysing full Java J2SE API would be major pain in the ass,
maybe smaller API should be revealed to the library.. =) Classloader can
help on this one..

--- Serialization ---

What comes to serialization, Java has versioning for classes and the
Serialization implementation. When serial uid of two classes match the
classes are expected to match. In this case class with new variables will
load accordingly to the specs, I don't remember weather they were
initialized as null or by default values by default. Pretty much as DGD
does.. Circular references can be also dealt with..

In case there would be kernel library taking care of the object
management, reference management and the classloading would enforce
serialization in some sence it would be possible to dump entire Java
worlds to disc..

--- THREADING ---

The real question between Java and DGD is threading. I recall Felix
stating that some of the solutions used by DGD prevent real
multithreading.

Such things would be for example state where you have thread:

 while(1) {
    System.out.println("Hello World");
 }

DGD recompilation happens between execution of LPC code "threads", this
way there is no code in excecution while upgrading. One would have to
abort thread to allow upgrade.

Also atomic code supported by kernel would break the multithreading..

I have no idea wheather Felix has come up with sane solution on this but
this is one of the big questions between DGD and Java architectures.

Yours,
 Sampsa Ranta


"
12.2 Loading of Classes and Interfaces

Loading refers to the process of finding the binary form of a class or
interface type with a particular name, perhaps by computing it on the fly,
but more typically by retrieving a binary representation previously
computed from source code by a compiler, and constructing, from that
binary form, a Class object to represent the class or interface.

The precise semantics of loading are given in chapter 5 of The Java
Virtual Machine Specification, Second Edition. Here we present an overview
of the process from the viewpoint of the Java programming language.

The binary format of a class or interface is normally the class file
format described in The Java Virtual Machine Specification cited above,
but other formats are possible, provided they meet the requirements
specified in ?13.1. The method defineClass of class ClassLoader may be
used to construct Class objects from binary representations in the class
file format.

Well-behaved class loaders maintain these properties:

    * Given the same name, a good class loader should always return the same class object.
"

"
5.3.4 Loading Constraints
Ensuring type safe linkage in the presence of class loaders requires
special care. It is possible that when two different class loaders
initiate loading of a class or interface denoted by N, the name N may
denote a different class or interface in each loader.

When a class or interface C = <N1, L1> makes a symbolic reference to a
field or method of another class or interface D = <N2, L2> , the symbolic
reference includes a descriptor specifying the type of the field, or the
return and argument types of the method. It is essential that any type
name N mentioned in the field or method descriptor denote the same class
or interface when loaded by L1 and when loaded by L2.

To ensure this, the Java virtual machine imposes loading constraints of
the form NL1 = NL2 during preparation (?5.4.2) and resolution (?5.4.3). To
enforce these constraints, the Java virtual machine will, at certain
prescribed times (see ?5.3.1, ?5.3.2, ?5.3.3, and ?5.3.5), record that a
particular loader is an initiating loader of a particular class. After
recording that a loader is an initiating loader of a class, the Java
virtual machine must immediately check to see if any loading constraints
are violated. If so, the record is retracted, the Java virtual machine
throws a LinkageError, and the loading operation that caused the recording
to take place fails.
"

"
12.7 Unloading of Classes and Interfaces

An implementation of the Java programming language may unload classes. A
class or interface may be unloaded if and only if its defining class
loader may be reclaimed by the garbage collector as discussed in ?12.6.
Classes and interfaces loaded by the bootstrap loader may not be unloaded.
"

_________________________________________________________________
List config page:  http://list.imaginary.com/mailman/listinfo/dgd



More information about the DGD mailing list