Undefined behavior is one of the things that was only recognized as a very bad idea in retrospect.
The first compilers were great hits and fortunately welcomed improvements over alternative machine language or assembly language programming. The problems involved were known, and high-level languages were specifically invented to solve these known problems. (The enthusiasm at that time was so great that HLLs were sometimes referred to as "the end of programming" – as if from now on we'd just have to write trivially what we wanted, and the compiler would do all the real work.)
Only later did we recognize the newer problems that accompanied the newer approach. If you are not on the computer that runs the code, there is a chance things will not silently do what we expected them to do. For example, assigning a variable would typically leave the initial value undefined; This was not considered a problem because you would not assign a variable if you did not want to store a value in it, or? Surely it was not too much to expect that professional programmers would not forget to assign the initial value, right?
It turned out that with the larger codebases and more complex structures made possible by more powerful programming systems, many programmers actually make such mistakes from time to time and the resulting undefined behavior has become a major problem. Even today, the majority of vulnerabilities, from tiny to terrible, are due to undefined behavior in one form or another. (The reason for this is that undefined behavior is usually very much determined by things at the next lower computer level.) Attackers who understand this level can use that latitude to make a program, not just unintentional things, but accurate to do things she want.)
Since recognizing this, there has been a general urge to banish undefined behavior from high-level languages, and Java has been particularly thorough in this regard (which was relatively simple, since it was designed to run on a custom virtual machine anyway). Older languages like C can not be easily upgraded without losing compatibility with the vast amount of code available.