It is easy to lose sight of the computer itself as an average programmer. Managed environments such as Java and .NET present programmers with an execution environment that makes their job easier. One of the most significant advantages of a managed platform over certain other languages (such as C++) is automatic memory management. Many programmers can slide by without knowing how the operating system manages memory, let alone how Java and .NET handle it. Programmer productivity is a great thing but in order to become a programmer that isn't just sliding by, getting the job done but not able to tackle certain classes of problems, one important area to study is how the underlying system works.
In the interest of peeking behind the curtain that is the computer, let's start with a short review of computer architecture.
The classic components of a computer are input, output, memory, and the processor (which is made of a control portion and a datapath portion).

The memory contains the programs that run on your computer and the data those programs need. We'll call this main memory since it is what is commonly known as "memory" in a computer. Physically, this is the memory chips that plug into your motherboard. You may have anywhere from 512 MB to several gigabytes of memory. However, the memory section of this big picture can apply to any form of memory storage.
The processor (aka the CPU, central processing unit) executes what are called instructions that are stored in memory. The control section of the CPU tells the datapath section what to do, such as add two numbers and store the result in a certain location in main memory. Processors also have a cache, which is memory closer to the processor, and thus is faster than main memory. We will get into the importance and opreation of a cache at a later date.
Programs are typically stored on a different type of memory, the hard disk. The CPU controls access to this device, transferring information from it to main memory. This is a function of the INPUT part of the computer.
The OUTPUT part of the computer is responsible for reading data from main memory.
Keep in mind that INPUT and OUTPUT are relative to the main memory, so input is data flowing to main memory, and output is data flowing from main memory. Any communication to and from the processor takes time. This is why cache is useful since communication is faster. Understanding how communication of data works in a computer gives you the information necessary to write algorithms that utilize memory better.
The processor executes instructions which might be familiar to you as assembly language or Java byte code or MSIL (Microsoft Intermediate Language) on .NET. These instructions are as close to the executing machine as possible while still being human readable. The processor sees these instructions as just a series of numbers, numbers that only have meaning to a specific processor and comprise its instruction set.
When you write a program in a high level language such as C++ (or C# or Java, among many others), what you write is translated into these intermediate instructions, part way between high human readability (C#) and low human readability (just numbers). Assembly language is known as a low level language because it is closer to the machine. A compiler is just a translator, taking code you can read and translating it to the numbers that comprise the instruction set of a processor. Output of .NET compilers on Windows is a DLL or an executable, same as C++ on Windows, all of which contain instructions for a machine, be it real or virtual.
I am over simplifying to some degree as there are many nuances to computer architecture and compilers, but this is a good big picture view. One of the most important concepts to understand is how memory is organized and how it works. Specifically, how it is used by both the operating system and a managed environment such as the CLR (common language runtime) on .NET. That will be addressed in a future entry.