It is quite simple, the char type in Java is just a number representing a character (or a character symbolized by its Unicode codepoint).
And Processing is able to show a single character (actually it decomposes strings into chars, so that's natural for it).
As you guessed, I am interested by the topic. So I started my own sketch. If you just want a final result, just wait a bit. If you want to develop your own, I can refrain from showing my sketch (only in early stages, anyway) if you want.
I just made a little proof-of-concept sketch, to test font usage (discovered I had to use a trick with createFont to avoid OutOfMemory error) and char display.
[EDIT: Added random selection of kana, pos, colors, etc.]
[EDIT 2: Added more fonts, discarding them if not found on system] 
Code:boolean bDebug = false;
String[] fonts = 
{
  "Arial Unicode MS", "MS Gothic", "MS Mincho", 
  "Batang", "Datum", "Gulim",
  "MingLiU", "SimHei", "SimSun"
};
PFont[] jFonts = new PFont[fonts.length];
char character;
int posX, posY;
void setup()
{
  size(700, 700);
  frameRate(1); // 1 frame per second... OK for a slideshow!
  // Define a dummy charset (1 char to use less memory)
  // because Processing really creates the bitmap font
  // even if it won't use it in this mode...
  // So if we don't do that, we will get an out of memory error!
  char[] dummy = new char[1]; dummy[0] = ' ';
  // Create fonts having Japanese chars
  int count = 0;
  for (int i = 0; i < fonts.length; i++)
  {
    jFonts[count] = createFont(fonts[i], 128, true, dummy);
    if (jFonts[count].getFont().canDisplay(demoChars[0]))
    {
	// This font is on the system and supports CJK
	count++;
	println("Using " + fonts[i]);
    }
    else
    {
	println(fonts[i] + " not found.");
    }
  }
  // Discard unsupported fonts
  jFonts = (PFont[]) subset(jFonts, 0, count);
  println(count + " fonts with CJK support found on this system.");
}
char[] demoChars =
{ 
  // The 10 most frequently used kanji (according to kanjidic)
  0x65E5, 0x4E00, 0x4EBA, 0x56FD, 0x4F1A, 0x5E74, 0x5927, 0x5341, 0x4E8C, 0x672C,
  // Semi-randomly chosen chars
  0x98DF, '\u9762', 0x96FB, 38588
};
void draw()
{
  background(#556677);
  if (frameCount % 2 == 1)
  {
    float r = random(3);
    if (r < 1)
    {
	// Hiragana
	character = (char) (0x3041 + random(0x54));
    }
    else if (r < 2)
    {
	// Katakana
	character = (char) (0x30A1 + random(0x57));
    }
    else
    {
	character = demoChars[int(random(demoChars.length))];
    }
    println(hex(character));
    posX = int(5 + random(width - 140));
    posY = int(130 + random(height - 150));
  }
  fill(128 + int(random(128)), 128 + int(random(128)), 128 + int(random(128)));
  textFont(jFonts[int(random(jFonts.length))]);
  text(character, posX, posY);
  
  if (bDebug)
  {
    // Testing limits
    fill(#FF0000);
    text(character, 5, 130);
    text(character, 5, 680);
    text(character, 565, 130);
    text(character, 565, 680);
  }
}