diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index 32bd0dec13..f6ba9524c6 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -14,16 +14,24 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jint code) { enum { LineSeparator = 100, - OsName = 101 + FileSeparator = 101, + OsName = 102, + JavaIoTmpdir = 103 }; switch (code) { case LineSeparator: return e->NewStringUTF("\n"); + case FileSeparator: + return e->NewStringUTF("/"); + case OsName: return e->NewStringUTF("posix"); + case JavaIoTmpdir: + return e->NewStringUTF("/tmp"); + default: throwNew(e, "java/lang/RuntimeException", 0); return 0; diff --git a/classpath/java/io/FileDescriptor.java b/classpath/java/io/FileDescriptor.java index c0404df92f..00b22d7073 100644 --- a/classpath/java/io/FileDescriptor.java +++ b/classpath/java/io/FileDescriptor.java @@ -7,7 +7,7 @@ public class FileDescriptor { final int value; - private FileDescriptor(int value) { + public FileDescriptor(int value) { this.value = value; } diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index e2856e5ea3..918ffb85d2 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -31,8 +31,20 @@ public final class Class { return getName(); } + private static byte[] replace(int a, int b, byte[] s, int offset, + int length) + { + byte[] array = new byte[length]; + for (int i = 0; i < length; ++i) { + byte c = s[i]; + array[i] = (byte) (c == a ? b : c); + } + return array; + } + public String getName() { - return new String(name, 0, name.length - 1, false); + return new String + (replace('/', '.', name, 0, name.length - 1), 0, name.length - 1, false); } public Object[] staticTable() { diff --git a/classpath/java/lang/Process.java b/classpath/java/lang/Process.java new file mode 100644 index 0000000000..94258a9407 --- /dev/null +++ b/classpath/java/lang/Process.java @@ -0,0 +1,18 @@ +package java.lang; + +import java.io.InputStream; +import java.io.OutputStream; + +public abstract class Process { + public abstract void destroy(); + + public abstract int exitValue(); + + public abstract InputStream getInputStream(); + + public abstract OutputStream getOutputStream(); + + public abstract InputStream getErrorStream(); + + public abstract int waitFor() throws InterruptedException; +} diff --git a/classpath/java/lang/Runtime.java b/classpath/java/lang/Runtime.java index 8854949f68..f5d81402cf 100644 --- a/classpath/java/lang/Runtime.java +++ b/classpath/java/lang/Runtime.java @@ -1,5 +1,11 @@ package java.lang; +import java.io.InputStream; +import java.io.FileInputStream; +import java.io.OutputStream; +import java.io.FileOutputStream; +import java.io.FileDescriptor; + public class Runtime { private static final Runtime instance = new Runtime(); @@ -25,6 +31,26 @@ public class Runtime { } } + public Process exec(String command) { + int[] process = new int[4]; + exec(command, process); + return new MyProcess(process[0], process[1], process[2], process[3]); + } + + public Process exec(String[] command) { + int[] process = new int[4]; + exec(command, process); + return new MyProcess(process[0], process[1], process[2], process[3]); + } + + private static native void exec(String command, int[] process); + + private static native void exec(String[] command, int[] process); + + private static native int exitValue(int pid); + + private static native int waitFor(int pid); + private static native void load(String name, boolean mapName); public native void gc(); @@ -32,4 +58,50 @@ public class Runtime { public native void exit(int code); public native long freeMemory(); + + private static class MyProcess extends Process { + private int pid; + private final int in; + private final int out; + private final int err; + private int exitCode; + + public MyProcess(int pid, int in, int out, int err) { + this.pid = pid; + this.in = in; + this.out = out; + this.err = err; + } + + public void destroy() { + throw new RuntimeException("not implemented"); + } + + public int exitValue() { + if (pid != 0) { + exitCode = Runtime.exitValue(pid); + } + return exitCode; + } + + public InputStream getInputStream() { + return new FileInputStream(new FileDescriptor(in)); + } + + public OutputStream getOutputStream() { + return new FileOutputStream(new FileDescriptor(out)); + } + + public InputStream getErrorStream() { + return new FileInputStream(new FileDescriptor(err)); + } + + public int waitFor() throws InterruptedException { + if (pid != 0) { + exitCode = Runtime.waitFor(pid); + pid = 0; + } + return exitCode; + } + } } diff --git a/classpath/java/lang/String.java b/classpath/java/lang/String.java index 54950aa1fe..47fbbb9af7 100644 --- a/classpath/java/lang/String.java +++ b/classpath/java/lang/String.java @@ -294,7 +294,9 @@ public final class String implements Comparable { return b; } - public byte[] getBytes(String format) { + public byte[] getBytes(String format) + throws java.io.UnsupportedEncodingException + { return getBytes(); } diff --git a/classpath/java/lang/StringBuffer.java b/classpath/java/lang/StringBuffer.java index ac90f68fc7..6bb212475d 100644 --- a/classpath/java/lang/StringBuffer.java +++ b/classpath/java/lang/StringBuffer.java @@ -50,6 +50,11 @@ public class StringBuffer { return this; } + public synchronized StringBuffer insert(int i, char c) { + sb.insert(i, c); + return this; + } + public synchronized StringBuffer deleteCharAt(int i) { sb.deleteCharAt(i); return this; diff --git a/classpath/java/lang/StringBuilder.java b/classpath/java/lang/StringBuilder.java index a951cef50d..dda0148296 100644 --- a/classpath/java/lang/StringBuilder.java +++ b/classpath/java/lang/StringBuilder.java @@ -135,6 +135,10 @@ public class StringBuilder { return this; } + public StringBuilder insert(int i, char c) { + return insert(i, new String(new char[] { c }, 0, 1, false)); + } + public StringBuilder deleteCharAt(int i) { if (i < 0 || i >= length) { throw new IndexOutOfBoundsException(); diff --git a/classpath/java/lang/System.java b/classpath/java/lang/System.java index ef0ff78435..26e4b63e8c 100644 --- a/classpath/java/lang/System.java +++ b/classpath/java/lang/System.java @@ -12,7 +12,9 @@ public abstract class System { private static final int Unknown = 0; private static final int JavaClassPath = 1; private static final int LineSeparator = 100; - private static final int OsName = 101; + private static final int FileSeparator = 101; + private static final int OsName = 102; + private static final int JavaIoTmpdir = 103; private static Property properties; @@ -42,8 +44,12 @@ public abstract class System { int code = Unknown; if (name.equals("java.class.path")) { code = JavaClassPath; + } else if (name.equals("java.io.tmpdir")) { + code = JavaIoTmpdir; } else if (name.equals("line.separator")) { code = LineSeparator; + } else if (name.equals("file.separator")) { + code = FileSeparator; } else if (name.equals("os.name")) { code = OsName; } diff --git a/classpath/java/lang/reflect/Field.java b/classpath/java/lang/reflect/Field.java index 9f744b2549..24297b4f84 100644 --- a/classpath/java/lang/reflect/Field.java +++ b/classpath/java/lang/reflect/Field.java @@ -51,22 +51,28 @@ public class Field extends AccessibleObject { Object v = class_.staticTable()[offset]; switch (code) { case ByteField: - return Byte.valueOf((byte) ((Integer) v).intValue()); + return Byte.valueOf + ((byte) (v == null ? 0 : ((Integer) v).intValue())); case BooleanField: - return Boolean.valueOf(((Integer) v) != 0); + return Boolean.valueOf + (v == null ? false : ((Integer) v) != 0); case CharField: - return Character.valueOf((char) ((Integer) v).intValue()); + return Character.valueOf + ((char) (v == null ? 0 : ((Integer) v).intValue())); case ShortField: - return Short.valueOf((short) ((Integer) v).intValue()); + return Short.valueOf + ((short) (v == null ? 0 : ((Integer) v).intValue())); case FloatField: - return Float.valueOf(Float.intBitsToFloat((Integer) v)); + return Float.valueOf + (Float.intBitsToFloat(v == null ? 0 : (Integer) v)); case DoubleField: - return Double.valueOf(Double.longBitsToDouble((Long) v)); + return Double.valueOf + (Double.longBitsToDouble(v == null ? 0 : (Long) v)); case IntField: case LongField: diff --git a/classpath/java/text/DateFormatSymbols.java b/classpath/java/text/DateFormatSymbols.java index 05408757f5..1661712a78 100644 --- a/classpath/java/text/DateFormatSymbols.java +++ b/classpath/java/text/DateFormatSymbols.java @@ -1,5 +1,13 @@ package java.text; public class DateFormatSymbols { + private String[] ampm = new String[] { "AM", "PM" }; + public String[] getAmPmStrings() { + return ampm; + } + + public void setAmPmStrings(String[] v) { + ampm = v; + } } diff --git a/classpath/java/text/MessageFormat.java b/classpath/java/text/MessageFormat.java index 0a2147a596..b61a311e20 100644 --- a/classpath/java/text/MessageFormat.java +++ b/classpath/java/text/MessageFormat.java @@ -3,7 +3,7 @@ package java.text; import java.util.Locale; public class MessageFormat extends Format { - private final String pattern; + private String pattern; private final Locale locale; public MessageFormat(String pattern, Locale locale) { @@ -19,4 +19,8 @@ public class MessageFormat extends Format { // todo return target.append(pattern); } + + public void applyPattern(String pattern) { + this.pattern = pattern; + } } diff --git a/classpath/java/util/Calendar.java b/classpath/java/util/Calendar.java index 66f3145f22..abb3236bbd 100644 --- a/classpath/java/util/Calendar.java +++ b/classpath/java/util/Calendar.java @@ -11,4 +11,77 @@ public abstract class Calendar { public static final int PM = 1; public static final int SECOND = 13; public static final int YEAR = 1; + + public static final int FIELD_COUNT = 17; + + protected long time; + protected boolean isTimeSet; + protected int[] fields = new int[FIELD_COUNT]; + protected boolean areFieldsSet; + protected boolean[] isSet = new boolean[FIELD_COUNT]; + + protected Calendar() { } + + public static Calendar getInstance() { + return new MyCalendar(System.currentTimeMillis()); + } + + public int get(int field) { + return fields[field]; + } + + public void set(int field, int value) { + fields[field] = value; + } + + public abstract void roll(int field, boolean up); + + public void roll(int field, int amount) { + boolean up = amount >= 0; + if (! up) { + amount = - amount; + } + for (int i = 0; i < amount; ++i) { + roll(field, up); + } + } + + public abstract int getMinimum(int field); + + public abstract int getMaximum(int field); + + public abstract int getActualMinimum(int field); + + public abstract int getActualMaximum(int field); + + private static class MyCalendar extends Calendar { + public MyCalendar(long time) { + this.time = time; + this.isTimeSet = true; + } + + public void roll(int field, boolean up) { + // todo + } + + public int getMinimum(int field) { + // todo + return 0; + } + + public int getMaximum(int field) { + // todo + return 0; + } + + public int getActualMinimum(int field) { + // todo + return 0; + } + + public int getActualMaximum(int field) { + // todo + return 0; + } + } } diff --git a/makefile b/makefile index 1cd670ddda..5303fbd1cb 100644 --- a/makefile +++ b/makefile @@ -16,8 +16,10 @@ src = src classpath = classpath test = test jscheme = $(HOME)/p/jscheme-7.2/src +swt = $(HOME)/p/swt-3.3/bin input = $(cls)/GC.class +swt-input = $(cls)/HelloSWT.class cxx = g++ cc = gcc @@ -139,10 +141,13 @@ args = $(flags) $(call class-name,$(input)) jscheme-command = jscheme/REPL build/make.scm -main commandMain "" +swt-command = $(call class-name,$(swt-input)) + .PHONY: build build: $(executable) $(input): $(classpath-objects) +$(swt-input): $(classpath-objects) .PHONY: run run: $(executable) $(input) @@ -162,25 +167,37 @@ test: $(executable) $(classpath-objects) $(test-classes) $(<) $(mode) "$(flags)" $(call class-names,$(test-classes)) .PHONY: run-jscheme -run-jscheme: $(executable) $(input) +run-jscheme: $(executable) LD_LIBRARY_PATH=$(bld) $(<) -cp $(cls):$(jscheme) $(jscheme-command) .PHONY: debug-jscheme -debug-jscheme: $(executable) $(input) +debug-jscheme: $(executable) LD_LIBRARY_PATH=$(bld) $(db) $(<) -cp $(cls):$(jscheme) $(jscheme-command) .PHONY: vg-jscheme -vg-jscheme: $(executable) $(input) +vg-jscheme: $(executable) LD_LIBRARY_PATH=$(bld) $(vg) $(<) -cp $(cls):$(jscheme) $(jscheme-command) .PHONY: profile-jscheme -profile-jscheme: $(executable) $(input) +profile-jscheme: $(executable) opcontrol --start; \ echo '(+ 5 6)' | LD_LIBRARY_PATH=$(bld) \ $(<) -cp $(cls):$(jscheme) jscheme/REPL; \ opcontrol --stop; \ opreport -l $(<) +.PHONY: run-swt +run-swt: $(executable) $(swt-input) + LD_LIBRARY_PATH=$(bld) $(<) -cp $(cls):$(swt) $(swt-command) + +.PHONY: debug-swt +debug-swt: $(executable) $(swt-input) + LD_LIBRARY_PATH=$(bld) $(db) $(<) -cp $(cls):$(swt) $(swt-command) + +.PHONY: vg-swt +vg-swt: $(executable) $(swt-input) + LD_LIBRARY_PATH=$(bld) $(vg) $(<) -cp $(cls):$(swt) $(swt-command) + .PHONY: clean clean: @echo "removing build" @@ -202,7 +219,8 @@ $(bld)/type-generator.o: \ define compile-class @echo "compiling $(@)" @mkdir -p $(dir $(@)) - $(javac) -bootclasspath $(classpath) -classpath $(classpath) -d $(cls) $(<) + $(javac) -bootclasspath $(classpath) -classpath $(classpath):$(swt) \ + -d $(cls) $(<) endef $(cls)/%.class: $(classpath)/%.java diff --git a/src/builtin.cpp b/src/builtin.cpp index 50630651bc..6020b759ce 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -419,7 +419,7 @@ Runtime_load(Thread* t, jclass, jstring name, jboolean mapName) t->vm->libraries = lib; } else { object message = makeString(t, "library not found: %s", n); - t->exception = makeRuntimeException(t, message); + t->exception = makeUnsatisfiedLinkError(t, message); } } @@ -558,11 +558,13 @@ jint JNICALL ResourceInputStream_read2(Thread* t, jclass, jlong peer, jint position, jbyteArray b, jint offset, jint length) { + if (length == 0) return 0; + Finder::Data* d = reinterpret_cast(peer); if (length > static_cast(d->length()) - position) { length = static_cast(d->length()) - position; } - if (length < 0) { + if (length <= 0) { return -1; } else { memcpy(&byteArrayBody(t, *b, offset), d->start() + position, length); diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 5485cff887..7b4a089f7d 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -153,10 +153,10 @@ findMethod(Thread* t, object class_, const char* name, const char* spec) { ENTER(t, Thread::ActiveState); - object n = makeString(t, "%s", name); + object n = makeByteArray(t, "%s", name); PROTECT(t, n); - object s = makeString(t, "%s", spec); + object s = makeByteArray(t, "%s", spec); return vm::findMethod(t, class_, n, s); } @@ -184,7 +184,7 @@ GetMethodID(Thread* t, jclass c, const char* name, const char* spec) return (vectorSize(t, t->vm->jniInterfaceTable) - 1) | InterfaceMethodID; } else { - return methodOffset(t, method); + return methodOffset(t, method) + 1; } } @@ -196,7 +196,7 @@ GetStaticMethodID(Thread* t, jclass c, const char* name, const char* spec) object method = findMethod(t, *c, name, spec); if (UNLIKELY(t->exception)) return 0; - return methodOffset(t, method); + return methodOffset(t, method) + 1; } inline object @@ -205,7 +205,7 @@ getMethod(Thread* t, object o, jmethodID m) if (m & InterfaceMethodID) { return vectorBody(t, t->vm->jniInterfaceTable, m & (~InterfaceMethodID)); } else { - return arrayBody(t, classVirtualTable(t, objectClass(t, o)), m); + return arrayBody(t, classVirtualTable(t, objectClass(t, o)), m - 1); } } @@ -634,10 +634,10 @@ CallStaticVoidMethod(Thread* t, jclass c, jmethodID m, ...) object findField(Thread* t, object class_, const char* name, const char* spec) { - object n = makeString(t, "%s", name); + object n = makeByteArray(t, "%s", name); PROTECT(t, n); - object s = makeString(t, "%s", spec); + object s = makeByteArray(t, "%s", spec); return vm::findField(t, class_, n, s); } @@ -820,7 +820,8 @@ GetStaticBooleanField(Thread* t, jclass c, jfieldID field) { ENTER(t, Thread::ActiveState); - return intValue(t, arrayBody(t, classStaticTable(t, *c), field)) != 0; + object v = arrayBody(t, classStaticTable(t, *c), field); + return v ? intValue(t, v) != 0 : false; } jbyte JNICALL @@ -828,8 +829,8 @@ GetStaticByteField(Thread* t, jclass c, jfieldID field) { ENTER(t, Thread::ActiveState); - return static_cast - (intValue(t, arrayBody(t, classStaticTable(t, *c), field))); + object v = arrayBody(t, classStaticTable(t, *c), field); + return static_cast(v ? intValue(t, v) : 0); } jchar JNICALL @@ -837,8 +838,8 @@ GetStaticCharField(Thread* t, jclass c, jfieldID field) { ENTER(t, Thread::ActiveState); - return static_cast - (intValue(t, arrayBody(t, classStaticTable(t, *c), field))); + object v = arrayBody(t, classStaticTable(t, *c), field); + return static_cast(v ? intValue(t, v) : 0); } jshort JNICALL @@ -846,8 +847,8 @@ GetStaticShortField(Thread* t, jclass c, jfieldID field) { ENTER(t, Thread::ActiveState); - return static_cast - (intValue(t, arrayBody(t, classStaticTable(t, *c), field))); + object v = arrayBody(t, classStaticTable(t, *c), field); + return static_cast(v ? intValue(t, v) : 0); } jint JNICALL @@ -855,13 +856,17 @@ GetStaticIntField(Thread* t, jclass c, jfieldID field) { ENTER(t, Thread::ActiveState); - return intValue(t, arrayBody(t, classStaticTable(t, *c), field)); + object v = arrayBody(t, classStaticTable(t, *c), field); + return v ? intValue(t, v) : 0; } jlong JNICALL GetStaticLongField(Thread* t, jclass c, jfieldID field) { - return longValue(t, arrayBody(t, classStaticTable(t, *c), field)); + ENTER(t, Thread::ActiveState); + + object v = arrayBody(t, classStaticTable(t, *c), field); + return static_cast(v ? longValue(t, v) : 0); } jfloat JNICALL @@ -869,9 +874,10 @@ GetStaticFloatField(Thread* t, jclass c, jfieldID field) { ENTER(t, Thread::ActiveState); - jint i = intValue(t, arrayBody(t, classStaticTable(t, *c), field)); - jfloat v; memcpy(&v, &i, 4); - return v; + object v = arrayBody(t, classStaticTable(t, *c), field); + jint i = v ? intValue(t, v) : 0; + jfloat f; memcpy(&f, &i, 4); + return f; } jdouble JNICALL @@ -879,9 +885,10 @@ GetStaticDoubleField(Thread* t, jclass c, jfieldID field) { ENTER(t, Thread::ActiveState); - jlong i = longValue(t, arrayBody(t, classStaticTable(t, *c), field)); - jdouble v; memcpy(&v, &i, 8); - return v; + object v = arrayBody(t, classStaticTable(t, *c), field); + jlong i = v ? longValue(t, v) : 0; + jdouble f; memcpy(&f, &i, 4); + return f; } void JNICALL diff --git a/src/machine.cpp b/src/machine.cpp index 44bf11d36f..bf9a33ef9d 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -794,7 +794,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) classObjectMask(t, classSuper(t, class_))); } else { object mask = makeIntArray - (t, ceiling(classFixedSize(t, class_), BitsPerWord * BytesPerWord), true); + (t, ceiling(classFixedSize(t, class_), 32 * BytesPerWord), true); intArrayBody(t, mask, 0) = 1; object superMask = 0; @@ -2334,7 +2334,7 @@ resolveObjectArrayClass(Thread* t, object elementSpec) object spec; if (byteArrayBody(t, elementSpec, 0) == '[') { spec = makeByteArray(t, byteArrayLength(t, elementSpec) + 1, false); - byteArrayBody(t, elementSpec, 0) = '['; + byteArrayBody(t, spec, 0) = '['; memcpy(&byteArrayBody(t, spec, 1), &byteArrayBody(t, elementSpec, 0), byteArrayLength(t, elementSpec)); diff --git a/src/machine.h b/src/machine.h index 4e5e01797f..2b48d10a4d 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1592,6 +1592,9 @@ instanceOf(Thread* t, object class_, object o); object classInitializer(Thread* t, object class_); +object +frameMethod(Thread* t, int frame); + inline void pushObject(Thread* t, object o) { diff --git a/src/run.cpp b/src/run.cpp index 7e75969db6..c4c9d236fa 100644 --- a/src/run.cpp +++ b/src/run.cpp @@ -368,10 +368,13 @@ invokeNative(Thread* t, object method) sp += 2; } break; - case POINTER_TYPE: - args[offset++] = reinterpret_cast - (t->stack + ((sp++) * 2) + 1); - break; + case POINTER_TYPE: { + object* v = reinterpret_cast(t->stack + ((sp++) * 2) + 1); + if (*v == 0) { + v = 0; + } + args[offset++] = reinterpret_cast(v); + } break; default: abort(t); } @@ -506,6 +509,14 @@ codeReadInt32(Thread* t, unsigned& i) return ((v1 << 24) | (v2 << 16) | (v3 << 8) | v4); } +inline void +store(Thread* t, unsigned index) +{ + memcpy(t->stack + ((frameBase(t, t->frame) + index) * 2), + t->stack + ((-- t->sp) * 2), + BytesPerWord * 2); +} + object run(Thread* t) { @@ -659,23 +670,23 @@ run(Thread* t) } goto loop; case astore: { - setLocalObject(t, codeBody(t, code, ip++), popObject(t)); + store(t, codeBody(t, code, ip++)); } goto loop; case astore_0: { - setLocalObject(t, 0, popObject(t)); + store(t, 0); } goto loop; case astore_1: { - setLocalObject(t, 1, popObject(t)); + store(t, 1); } goto loop; case astore_2: { - setLocalObject(t, 2, popObject(t)); + store(t, 2); } goto loop; case astore_3: { - setLocalObject(t, 3, popObject(t)); + store(t, 3); } goto loop; case athrow: { @@ -1164,12 +1175,12 @@ run(Thread* t) case ShortField: case FloatField: case IntField: - pushInt(t, intValue(t, v)); + pushInt(t, v ? intValue(t, v) : 0); break; case DoubleField: case LongField: - pushLong(t, longValue(t, v)); + pushLong(t, v ? longValue(t, v) : 0); break; case ObjectField: diff --git a/src/system.cpp b/src/system.cpp index 99cd06d576..420dfe94bd 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -544,6 +544,7 @@ class MySystem: public System { Library(this, p, n, mapName, next); return 0; } else { +// fprintf(stderr, "dlerror: %s\n", dlerror()); return 1; } } diff --git a/test/HelloSWT.java b/test/HelloSWT.java new file mode 100644 index 0000000000..8cbd10b2b6 --- /dev/null +++ b/test/HelloSWT.java @@ -0,0 +1,25 @@ +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Label; + +public class HelloSWT { + public static void main (String[] args) { + Display display = new Display(); + final Shell shell = new Shell(display); + RowLayout layout = new RowLayout(); + layout.justify = true; + layout.pack = true; + shell.setLayout(layout); + shell.setText("Hello, World!"); + Label label = new Label(shell, SWT.CENTER); + label.setText("Hello, world!"); + shell.pack(); + shell.open(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) display.sleep(); + } + display.dispose(); + } +}