Wednesday, July 22, 2009

Java is not the JVM

For many IT people, it sounds funny to assert that the Java language has nothing to with the JVM itself. But as incredulous as it sounds, this is actually true. Let me explain, using some code as a shallow illustration how this is the case.

When I was hacking at the Java bytecode level, one of the things that I do is to optimise for memory efficiency. There is a need for storing an array of booleans, and the most obvious way of saving memory is to store it at a bitwise level, by stashing 8 boolean values within a byte.

Within the JVM, booleans are stored as bytes (executionally, they are worse: the VM treats booleans as ints!). Furthermore, in Java, there isn't a low-level means of utilising booleans as integral types like C can. If you had to write code in pure Java, at best you'll end up writing code like this:


// assume z == boolean[8]
byte b = 0;
for ( int i=0; i < 8; i++ ) {
if ( z[i] == true ) {
b |= ( 1
<< i );
}
}



Unlike C, the code is clunky, as you are having to perform a conditional check on a boolean, before you can perform bitwise operations on the values, because Java considers booleans as a non-integral type. How annoying!

But this constrain only affects the Java language - the same rules do not apply when it comes to the JVM. On the VM, it is perfectly legit for you to express code like this:


// assume z == boolean[8]
byte b = 0;
for ( int i=0; i < 8; i++ ) {
b |= z[i] << i;
}


However, just about any Java compiler disallows this code to compile - the operations on the boolean violates type-safety. But don't blame the compilers, they are just conforming to the language specifications. But since the JVM has nothing to do with the Java language, there is nothing illegal in doing so outside the Java language, let say by using bytecode assembly. Here's an equivalent, using jasmin assembly code:

.source BooleanToByte.j
.class BooleanToByte
.super java/lang/Object

.method public static main([Ljava/lang/String;)V
.limit stack 4
.limit locals 3

iconst_0
istore_1 ; byte b = 0;

iconst_0
istore_2 ; int i = 0;

LOOP:

iload_2
bipush 8
if_icmpge EXIT_LOOP: ; if i>=z.length exit loop

; here's the magic code that allows you to do direct
; bitwise
b |= z[i] << b="">
iload_1
aload_0
iload_2
baload
iload_2
ishl
ior
istore_1

iinc 2 1
goto LOOP:

LOOP_EXIT:

return

.end method

The jasmin code will probably assemble, but don't expect the JVM to execute it; it serves only as an example, and lacks a few things (I'm missing the constructor block and other nitty gritty little things that's needed to satisfy the bytecode verifier). It is but a case study to separate the JVM from the Java language as people typically assume.

There has been a number of other languages that has since mushroomed which relies on the JVM as its core; these languages include Groovy, Scala, Jython and JRuby, many of which are rather interesting, although they are more of a curiosity at this stage - I've yet to see any of these implementations deployed in a production environment, although I don't say that as a criticism of any of these languages. In fact, I am actually quite impressed with the JRuby, and I recommend you give it a try. It's very faithful to the actual Ruby implementation and allows you to use Java directly. Good fun, I'd say, especially when it combines the expressive of the former with the features of the latter. It's quite impressive that the JVM has been able to be so versatile in allowing other languages to plug into it directly.

GDB: Relaying Trapped OS Signals

By chance, I have managed to land myself in a situation where the bug occurs only at a signal handler. In my situation, this means that it happens only when I try to kill the program using a SIGINT, or more commonly known as the 'ctrl-c' keystroke.

GDB usually traps this signal, and other signals such as SIGSEGV (Segmentation Fault), so that you can trace buggy behaviour that is causing your application to fail. But once in a while, the error may occur after the signal is sent, when the code failure resides within the signal handler.

However the default behaviour of GDB is to trap these signals and subsequently consume them, in effect preventing the bug from occurring. To prevent unwanted behaviour in rare cases such as mine, you need to issue the following command:


(gdb) handle SIGINT pass


Given that GDB utilises this signal internally, it will ask you for a confirmation to change it. Say 'y' to it, and GDB will correspondingly pass the signal to the application after trapping, which will give you a chance to debug the handler code that is causing the bug.
Sunday, July 19, 2009

GDB's Conditional Breakpoints

Conditional Breakpoints for Scalar Types

Let's assume that you, the brilliant hacker, has coded up some really uber-cool stuffs, like this piece of code below:


1: for ( int i = 0; i < gazillion; i++ ) {
2: doSlightlyBuggyButUberCoolStuffs(i)
3: }
4:
5: void doSlightlyBuggyButUberCoolStuffs(int i) {
6: // your code here that needs some
7: // fixing before it becomes uber-cool
8: }


It is doing all the cool stuffs as intended, but somehow something always goes wrong when the code executes up to 2147483648, which is kind of puzzling.

So what to do?

You may be tempted to breakpoint at line 5, at the start of the doSlightlyBuggyButUberCoolStuffs():


(gdb) br doSlightlyBuggyButUberCoolStuffs


And gdb dutifully does what it's told; every single time doSlightlyBuggyButUberCoolStuffs() gets executed, it stops and waits for you to act on it:


Breakpoint 1, doBuggyButUberCoolStuffs (i=1) at test.cpp:6
6: // start of your uber-cool code
(gdb) c

Breakpoint 1, doBuggyButUberCoolStuffs (i=2) at test.cpp:6
6: // start of your uber-cool code
(gdb) c

.....

Breakpoint 1, doBuggyButUberCoolStuffs (i=100) at test.cpp:6
6: // start of your uber-cool code
(gdb) c


After 100 iterations, you think you've had enough! So it's time to do it the smart way, by setting a conditional:


(gdb) br test.cpp:2
Breakpoint 1 at 0x1234: file test.cpp, line 2.
(gdb) cond 1 i==2147483648
(gdb) run


After the breakpoint is set, gdb only notifies you when the loop is at its 2147483648th iteration:


Breakpoint 1 at 0x5678: file test.cpp:2
2: doBuggyButUberCoolStuffs(i)
(gdb) s
6: // start of your uber-cool code
(gdb) p i
$1 = 2147483648


Jackpot! You're now at the 2147483648th iteration! And very soon after, you found the offending piece of code, caused by a numerical overflow of a signed integer. Another bug trampled, and peace returns to your realm once more.


Conditional Breakpoints for char* Strings
But very soon after, you run into another irritating problem which is happening within another section of your uber-cool code. This time, the conditional depends on parsing a huge portion of text that comes from, um..., /dev/random :P


1: while ( true ) {
2: char* c = getStringFromDevRandom();
3: launchNuclearMissileIfCodeMatch(c);
4:}


Somehow, you are absolutely convinced that /dev/random will eventually provide correct codes to launch the nuclear missile, but given that launchNuclearMissileIfCodeMatch() is a really top-secret and highly obfuscated code residing in an external library called libtopsecret.so, it isn't such a good idea to debug into the call unless you want the NSA bursting through your front doors...

But since you do know the launch code (it's one of those things that you'll have to kill your friends if you ever told them), you can perform a conditional check on the string, and breakpoint at it to tell you if the secret code is ever generated by /dev/random to find out if launchNuclearMissileIfCodeMatch() is really a hoax:


(gdb) br test.cpp:3
Breakpoint 1 at 0xdeadbabe: file test.cpp, line 3.
(gdb) set $secret_code = "MyUberSecretivePassword"
(gdb) cond 1 strcmp ( $secret_code, c ) == 0
(gdb) run


And then, you let your code run... (!)

Well, unfortunately, you get sick of sitting around and waiting for it to happen after a whole day. It seems like /dev/random doesn't really generate your uber-secret nuclear launch codes as frequently as you would like to think. In the meantime, the world thanks their lucky stars that you haven't caused a nuclear winter to materialise just yet... :)
Saturday, July 11, 2009

How to lose weight and be healthy

I have little patience with people who complain about their weight problems, and for a good reason - I have a really simple way for losing weight which does not involve going on a crazy exercise binge or starving yourself silly. Sounds miraculous? Well, read on.

The easy part that you already know, is to make some wise choices about your diet, exercise moderately, and be consistent at both. Yes, it is both sensible and achievable.

The second part is usually what squeezes the life out of one, when I say:

"Stop eating chocolates, cake and ice-cream!"

My advice makes me sound like I'm a Nazi Dictator violating their 8th Amendment rights. But no, and let me reassert this again, it is that simple.

I'm deadly serious.

Chocolates, cake and Ice-cream belong to a broader category I classify as 'leisure food'. It's leisure because people eat these food for their own enjoyment, not for sustenance. This applies to all other snacks (cookies, biscuits, sweets, chips and flavoured drinks) - if that is what you are usually consuming when you're not hungry, then you shouldn't be having it.


"But, but... that's impossible!"

I'll tell you a story about a friend of mine. Let's call him 'Bryan'. (Oh, that is your real name! Let's see how long before someone points you to read this entry :P) Bryan has a minor weight issue, and he once told me about this amazing story that his household fridge was like The Bag of Holding; each time he opens it, there will be a slice of chocolate cake or other sweet delights waiting for him. No surprises to why he isn't able to keep his hands off the sugary stuffs.

Now let me tell you another story of another friend of mine. Let's call him 'Vincent'. (Oh hey, that's me!) Vincent grew up in a poor household where there's no cake awaiting for him in the fridge any time he opens it. In fact, there's nothing there for him whenever he opens it. Poor Vincent! You might even begin think that his childhood is real deprived!

On the contrary, Vincent had never been hungry in his life; there is always food on the table, and the meals involve a simple serving of rice, vegetables, and either eggs, chicken, fish or other protein sources. Given the tight budget Vincent's mum had, there wasn't enough money to buy chocolates, snacks and fizzy drinks anyway. 20 years later, Vincent do not have much cravings for these 'leisure foods' . To others, he just seems to have an incredible self-control.

No, this isn't a tit-for-tat competition here, all I'm saying is that good moderate choices makes harder things easier in the long run.

So what do you do if you grew up in the life of Bryan?

Start small, and be consistent. Consistency is the key, my friend. In the long run, it will get easier for you. Just don't get into the delusion of wanting instant results.

There is this one other issue, like what if:


"I get hungry really easily!"

That is why you should stop eating chocolates, cake and ice-cream! And eat more meat!

Some of you might be puzzled. More meat? Let me explain why in my own personal, anecdotal example. If you ever read food labels, you'll find that a 40g bar of Cadbury's chocolate contains 205 Calories of energy. In comparison, 125g of chicken breast contains only 133 Calories of energy!

I'll answer how these number translate to in human terms. If I have more than a good portion of chicken for lunch, say 250g, I'll have consumed 266 Calories and it will keep me from being hungry till dinner. In comparison, if I had two chocolate bars for lunch, I would have consumed 410 Calories of energy AND I'll be hungry again 2 hours later!

I'm aware that there are some scientific studies out there that supports my claim, but what's more important, is that I know it works for me. This I want you to keep in mind. I certainly can tell that something within meat (or protein, I suspect) keeps one from feeling hungry sooner. Carbohydrates just don't do the same thing. It's no wonder some people swear by faddish regimes like the Atkin's Diet.

But I do not recommend anybody from trying funny diet plans, or simply going on diets at all. Firstly, if you are starving yourself, you are doing it wrong. Because it'll never work - primal instinct will always override any artificial discipline that you try inflicting on yourself. Secondly, diets promote deprivation, and the deprivation of essential nutrients to your body is certainly always harmful. All I'm saying, is to cut down on unnecessary leisure food carbohydrates, and have more meat if your body reacts to hunger the same way as I do. In addition, do stick to what the doctors recommend with regards to healthy servings of fruits and vegetables.


Eating less is good for you

Recently, it's been proven that caloric restriction will improve health and extend longevity. And this includes us primates, and not just in lab mice. If you're too lazy to read the links, here's a visual difference between two monkeys where one is on caloric restriction and the other isn't. Guess which one is which?


If you're cringing in horror about how miserable the rest of your life will be starving yourself, think again. You'll be surprised how it does not involve starving. There's no contradiction, and I'll use myself as an example. For the numbers to make sense, we need to know how much Calories I need - and there are plenty of calculators out there that will help to figure this out, Google it.

Now, for a 30 year-old, 1.75m, 65kg guy, my Caloric requirement is about +/- 2500 Calories, depending on which calculators used. A 25% Caloric reduction is what they've used in the scientific studies, so that brings my figure to 1875 Calories. Now, lets calculate what I eat on a given day, which includes breakfast, lunch and dinner with no snacks.

Breakfast
4 slices of bread, 68g - 200 Calories
Nutella, 18g spread! - 98 Calories
Tea - 2 Calories

Lunch
200g Chicken - 212 Calories
250g Rice - 867 Calories

Dinner
300g Salmon - 447 Calories
100g Broccoli - 35 Calories
133g Apple - 65 Calories

Total Calorie Count : 1926 Calories

It's slightly more than 1875, but it's not too far off range. And I'm not rationing myself either - I've given generous estimates for the spreads (18g spreads to 67g of bread!), and dinner is 2 portions of Salmon (supermarkets estimate of portion sizes are ridiculous!). Give and take, that is what I normally have without having to feel hungry at all, it's quite amazing to know that I'm still within their bounds of 'Caloric Reduction'!

If you've noticed, it is the carbohydrate foods that are giving an amazingly high Caloric count - look at rice at 867 Calories at 250g! And I never knew this until I looked this up myself!

More chicken from now on, please!


Supersized Nations

Being fat is a peculiar problem that exists only in industralised nations. No surprises, since that is where all the money is. Indulgence is an economic problem if you actually think about it - it only afflicts people who can afford it. I'm just 'lucky' I grew up in a circumstance where I do not have a luxury to indulge in leisure foods, although this doesn't make the make me the model case study for solving the fat nations problem.

It is really not a problem if you understand this is how capitalism works. Businesses are incentivised to create things you want, and for food companies, to create foods that are tasty, so that you'll buy them. Tasty foods means that you'll want to have more. People often cite the reasons of growing fat on the an abundance of food and the general lack of exercise in the modern world - it is true, but it's no more correct to blame it on the companies who make tasty foods, than to attribute blame on themselves. If food companies are predatory to the addiction of your taste buds, should we go after them like we do on hard drugs?

I like capitalism - it is your prerogative to see how best to spend your money, so it is within your rights to eat yourself silly, and then spend a fortune on treatment - that is a personal choice.

But it irks me to see how governments are socialising these costs at the expense of sensible people - it's just one of the things in our society I like to describe as 'mad'. If it's 'too big to fail', nobody should have allowed it to grow that big in the first place. So far, governments are just plain inept at dealing with both supersized companies and supersized people.

So, do not bring weight loss problems as a conversation to my dinner table. And if anybody does have the temerity to raise it, be prepared for a session of ridicule - and if he or she takes it in good humour, maybe I'll refer them to what I have to say on this subject matter.
Friday, July 03, 2009

Scottish Whisky

Feels like you've drunk a cigar.