Discuss the future of 4k contest

Looks OK to me. I haven’t used git or mercurial, but they have Eclipse plugins, so I’m sure I can learn.

If you email me your pikacode id, I can add you as a committer. Same goes for anyone else on this list who wants to contribute. You can find my email on my profile page. Apparently the option “hide my email” doesn’t seem to do what I thought it did. You can try the personal message on this site instead.

Well I’ve hacked together a pack.gz loader, but it does require a temporary file to put the unpacked jar in. Any better ideas?


            URL path = new URL("http://java4k.com/applet.php?gid=451");
            GZIPInputStream gzistream = new GZIPInputStream(path.openStream());
            FileOutputStream fostream = new FileOutputStream("/User/Java/AppletTest/test/temp.jar");
            Unpacker unpacker = Pack200.newUnpacker();
            JarOutputStream jostream = new JarOutputStream(fostream);
            unpacker.unpack(gzistream, jostream);
            gzistream.close();
            jostream.close();
            JarFile jar = new JarFile("/User/Java/AppletTest/test/temp.jar");

I’ve stuffed this in a custom classloader, but need to think about this a bit more. Probably need a method to set the location of the gzip, before using the classloader.

Security is also a pain, as unless I load all the games in before setting the SecurityManager, I lose access to the files. Might have to allow network access.

Creating an AppletStub with an isActive() method works fine.

I found an alternative library that can load a zip file into memory (https://truezip.java.net/), because the ZipInputStream doesn’t handle all cases of zips.

Yes. Proper security managers are quite the pain. The only way I could explicitly get it to work was to load a policy file, where the executing class is in the list of allowable classes, and explicitly limit everything else (https://pikacode.com/groboclown/java4k-launcher/file/default/launcher.policy). I also limited my applet class loader to prevent the loading of any of these special classes, to prevent a backdoor.

I wrote some similar code earlier this week to load gzip, pack200 and gizp+pack200 files. I didn’t find an in memory way to handle unpacking, I did it the same as you. A few differences though: the files should be put in java.io.tempdir, no hard-coded paths; needs to handle files that are only pack200, or only gzipped. The files need to be cleaned up after unloading. And as with my previous code and groboclown’s, you definitely need a separate classloader per applet, since otherwise there might be namespace conflicts (eg: two applets both with a Main-class named “A” in the default package.) I’ll have a look tomorrow at how groboclown handled it in his code, I expect he (or she ;); half my team are women) has already covered most of this.

Put this in your policy file to grant access to only the system defined temp directory.

permission java.io.FilePermission "${java.io.tmpdir}/*", "read, write, delete";

Note that I excluded execute, which prevents running anything outside the app’s sandbox; and also readlink, in case someone’s dumb enough to put a link from the tempdir to somewhere else on the file system. So if malicious code gains access to the app’s permissions (say because we goofed with the codebase path), the only bad stuff it can do is access or delete existing files in the tempdir (and, I suppose it could fill the harddrive with junk data?)

I’m looking at tightening the permissions for the launcher. So far this seems sufficient:


  permission java.lang.RuntimePermission "createClassLoader";
  permission java.lang.RuntimePermission "closeClassLoader";
  permission java.net.SocketPermission "java4k.com", "connect, resolve";

  permission java.io.FilePermission "${java.io.tmpdir}/*", "read, write, delete";

  permission java.util.PropertyPermission "com.sun.java.util.jar.pack.*", "read";

  permission java.io.FilePermission "${java.home}/lib/*", "read";

Also of use to anyone working with policy files, I recommend including them in the jar and loading them in the first few steps. Otherwise, you’re relying on the calling process to pass the policy file as a command line parameter - if they don’t supply it, the app loads with the default which seems to be AllPermissions. To load from a jar resource:


		// Load a security policy to restrict access.
		System.setProperty("java.security.policy", Java4KLauncher.class.getResource("resources/java4k.policy").toString());
		System.setSecurityManager(new SecurityManager());

Is to possible to allow the downloader application to create class loaders, but prevent the loaded Applet from creating one. I suspect, if it could, it might be able to load a user supplied class instead of a system supplied class, which could be used for privilege escalation. Ideally I’d like to create a single user class loader before loading the security manager, and then flush out classes cached with it, so as to be able to reuse it, subsequent to the security manager being loaded. Somewhat handicapped by not knowing what I’m doing ;D

Edit: Ok, I can use codebase in the policy file to prevent the Applets creating class loaders.

Edit 2: Looks like one has to do this:

Must the launcher also be 4k?

Yes, that’s why my code posted at the start of this thread creates one classloader per applet. Once a classloader has loaded the meta data for a class, it isn’t possible to “flush” that definition. So for example, you can’t load a new version of a jar with the same classloader. I really wouldn’t suggest writing your own classloader, if that’s what you’re thinking (based on your comment “System classloader is not suitable for this task.”) You’re a lot more likely to introduce security holes implementing your own loader. If you look at groboclown’s policy file, you’ll see that the default permissions he granted to all code are only those available to applets. So if we correctly configure the security policy so that we only grant classloader privileges to the launcher and not to all code, that should close the hole you described. Further, if we restrict the launcher as I described a couple of posts above your comment, even code that loads its own classes won’t be able to do much besides get stuff from the tempdir or from java4k.com. It won’t be able to execute code locally, or load its own security manager, or start a daemon thread, even do stuff like access the clipboard.

Back on classloaders, I wrote a plugin architecture for a web portal about 10 years ago, and the four take-aways were:

  • the plugins should be in separate jars, outside the classpath of the main app
  • they shouldn’t be loaded with the default classloader (because then you have to restart the application to load changes to the plugins). Instead use either one classloader per plugin, which can be replaced on the fly when a plugin needs to be updated; or use one classloader for all plugins, which means reloading all plugins when any of them needs updating.
  • depending on how you configure log4j, it may hold back-references to a classloader, preventing it from being gc’d, so be careful
  • if you don’t release classloader references, you can quickly run out of permgen space, because that’s where class metadata is stored

These days tools like jvisualvm and Eclipse’s MAT plugin make it much easier to watch for problems like the ones I ran into back then.

Please god, let that be sarcasm! ;D

One thing to note about using the SecurityManager - some of the Oracle documentation makes note that the default security manager isn’t restrictive enough on the thread group permissions. Special care must be taken to ensure that the applet cannot create a new thread group outside its original parent.

I so want this compo to carry on, but I can’t see how a launcher do that… asking people to sacrifice personal security for all 4K games seems worse to me than asking them to do so for just one of them.
I spend a lot of time telling people to be careful when they click ‘OK’, and here’s this thread trying to get people to open up their machines to potentially malicious content. Why should they trust us? It’s no go for me.
I’m working on a game ATM where all the whole toolchain is pure java but the delivery is javascript/HTML5. It makes sense to me.
Maybe we should split it up - 4K source JS for safeys and 4K applet for dare-devils.
It is JAVAscript after all!

One week to go, and I’m clueless as to what to do about this years contest. Is a launcher going to solve our problems? Although I appreciate the efforts, I’m unsure and skeptical about the outcome, and I don’t want to reinvent the JVM.

I don’t want to be pessimistic, but is it time to admit defeat? Java seems like a total basket case. Our platform got wiped out. There’s no way you can deploy java applets on the web anymore, webstart is a non-starter, and nobody will download an exe installer that includes a jre to run a 4k game. It’s like all the choices have run out. The dream that applets would be universal is pretty much toast.

Also, it is a changed world. Even flash games are in defense, nobody is willing to spend money developing them when they could be making them as iOS/android apps. Heard of a popular flash game lately?

Honestly, and to be realistic here, it doesn’t look like I’m going to manage another 4k contest. Although the 4k contest has been great fun and a productive experiment, I’m now more interested in putting my effort into something that’s more productive and useful, than to go through the trouble of trying to squeeze out a yet another contest, especially not when the technology doesn’t want to play nice with you anymore.

In truth, this competion has always been by Devs for Devs. I would be happy for just jars. The launcher just makes it easier and minimise the already minuscule security risk of the entrants.

I say leave the competiton as it stands and deliberate next year later.

I am the same opinion as moogie and the launcher sounds great, but I like the Javascript idea too.

One possible idea:
All devs have to submit a normal pack200 Java 4k version of their game but if they want they can upload a Javascript version of the game. So everybody can play the game.
I made a little JS template. With that template I ported all my 4k games (last year and my entries for this year … so please start the contest =) ) in under 2 hours (for one game).

The disadvantage is that my template is only for 2d games and you have to check whether the game is the same as the 4k version …

But I can understand appel too, why to spend so much time for a contest when nobody can play the results (only applet version) … not easy …

Am with Appel here. Java applets are deader than an extinct deceased dodo. Time to move on, time for Android!!!:-

My proposal is as follows:-

  • Java4K is changed to an Android only contest.
  • Same 4K limit applies, you can write your game/logic using an Android SurfaceView/Canvas or equivalent.
  • Obviously we have the Android set-up bloat. A game .apk would probably be around 250-300K. This is where dex2jar http://code.google.com/p/dex2jar/ comes in. This is handy little tool, which will convert your .apk to a .jar file. The resultant .jar file can be checked to see if the custom code is under 4K (maybe a script on the java4k website when the dev submits their apk).
  • Games (.apk) can still be hosted on Java4k (disk space permitting, appel?), no need to submit to Google Play. Just a little message on the website instructing the ppl to change their Android settings to allow installation of games from Non-Market sources.

The rules would obviously disallow images in resources, running external Intents etc. A few things would need to be ironed out, for example whether to allow 1 SurfaceView XML layout etc. Only the start-up Icon would be allowed.

I just tried this now. I created a little program to move a circle around my phone. My main activity had 100+ lines of code and uncompressed (after dex2jar) .class file was 3k. (The resultant .jar file also had 10 other R**.class files, I guess we can ignore these).

My 2cents.

One option is to just go ahead with it as-is, and just see what happens. We’re only speculating on what the impact will be on the 2014 contest, it could turn out OK in the end. It seems a shame to cancel a long-running contest just because there may a lower turnout this year.

I had a reply to SimonH’s post ready, rehashing the problems the launcher addresses and the ones that it doesn’t, but the points are moot if there’s no contest.

Is it possible to run a pack200 jar from the command-line without extracting it assuming that the game runs in a standalone window?

In principle it should be possible using a classloader which handles pack200 and is injected into the bootclasspath with command-line options. Probably easier to write a launcher which uses a pack200 classloader, though.

I do not agree with all that security talk.

Just look at Ludum Dare, how many entries are native windows binaries that can contain literraly anything? And I never heard of a bogus ludum dare entry.
Many of those native binaries are top ranked, which means, people do play them.

This is not new in java, I’ve always heard that - and never really agreed.
Why is a java runnable so much heinous and dangerous than a demo exe game built in C?

It is cool that applets once made our games a click away from the players, but having an executabe never prevented other competitions from happening.

Maybe we are just overestimating the unwillingness people have of download an exe and run it.

Because C programs don’t just execute when you visit a web page. That is the one difference.

Any other method of deployment is not really any more or less safe than native though, so it’s all down to differing levels of inconvenience and brokenness.

Cas :slight_smile: