Jump to content

Programski, Markup Jezici, 3d Animacija I Slicno..


+Abigail+

Recommended Posts

Za Gaspar Graula. Moderatore molim da obrisu posle upotrebe da ne arcimo bespotrebno bazu.

 

 

The Tragedy of Microsoft and Java

by Howard Gilbert

Technology and Planning, Yale University

05 Feb, 2003

 

It could have been worse, but then they would have had to hire more lawyers.

 

Each Java program runs in an environment called the "Java Virtual Machine". As the name suggests, the JVM creates a special environment isolated from the rest of the operating system. Sun regards this isolation as a feature. It preserves the purity of Java and ensures that Java programs cannot become dependent on features available in only one operating system. However, Java programs also cannot communicate with programs running outside the JVM.

 

There is an exception to the isolation. The Java 2 Extended Edition (J2EE) standard defines a special Java environment hosted by a Application Server that becomes a "container" for network services implemented in Java. A particular type of Java class, the "Enterprise Java Bean" (EJB) exposes services and data that can be accessed by other programs running on the same machine or elsewhere in the network. Other Java programs can call the EJB through a Java-only service called RMI. Applications written in other programming languages use CORBA.

 

Now suppose that someone created an standard JVM that could turn any Java class into an EJB just by adding a comment to the source file. Not a big expensive Application Server that costs tens of thousands of dollars, but an ordinary Java runtime that runs ordinary applications and is given away free to everyone. Any program written in any language could call Java code for services, and Java code could easily call other programs on the same or on other machines in the network. Suppose they did it back in 1998, back before there was a Java 2 let alone an Extended Edition.

 

That is what Microsoft did. In early 1996 they signed an agreement with Sun and began a large scale investment of money and manpower to create what they regarded as the best Java development and execution environment possible. However, Microsoft's view of that environment was different from Sun's view. Microsoft wanted Java to be the most powerful language possible. Certainly the people working on Microsoft Java (if not those working on Visual Basic) wanted Java to be the best language for developing Windows applications. To achieve that they made modifications to the JVM that anticipated some of the ideas Sun would later apply to J2EE. However, Microsoft based its design on the standards it had already adopted for all its other products. Thus the Microsoft JVM communicated to other programs using COM instead of CORBA.

 

This made Sun angry. Sun wanted to retain control over Java and had philosophical disagreements over the direction of the Microsoft changes. Initially, Sun came to the table with a fully implemented compiler (written itself in Java), a runtime environment (the Java Virtual Machine or JVM), and a set of class libraries. Sun wanted to leverage its copyright ownership of this initial bundle of code to force compatibility of all versions of Java running on all systems.

 

Copyright protects an expression of an idea but not the idea itself. If the behavior of a language can be completely described, nothing in the law will prevent someone else from creating an independent implementation of the language and possibly alternate versions. In practice, however, the large and inadequately documented Class library posed a more serious problem than the language itself. Sun expected that Microsoft would be stuck optimizing the speed of the runtime system while Sun could control the content of the Class libraries that really shaped the language.

 

By bridging the closed Java runtime environment to the rest of the operating system, Microsoft had completely upset that calculation. With the Microsoft tools, a developer could turn Word, Excel, or Media Player into what appeared to be a Java Class. Microsoft had make Java a powerful Windows development language, but that was not what Sun had in mind. Rather than accept the evolutionary change, Sun went to court.

 

Ownership

Nobody has ever tried to assert ownership of a programming language. Most programming languages have an original inventor: FORTRAN (Backus), COBOL (Hopper), APL (Iverson), LISP (McCarthy), BASIC (Kemeny), Pascal (Wirth), C (Ritchie), C++ (Stroustrup). Once the language is launched, however, others are free to build on it and create new variations.

 

The strongest attempt to control a language was the Department of Defense management of Ada. They developed an independent battery of compatibility tests and a certification program. The purpose was to insure that previously developed Ada components could be reused on new systems and hardware. Nobody could add extensions to the Ada language, but the only enforcement mechanism was to drop certification and prohibit the use of the registered trademark name "Ada" on the result. So, for example, the Oracle programming language PL/SQL could be based on Ada as long as it didn't use the name.

 

Sun also trademarked the name "Java" as it applied to programming languages. This did not effect Microsoft as long as it called its languages J++ or J#. As to whether Sun had more control over Microsoft's development, that depended on how you read the contract.

 

History

In March, 1996 Microsoft and Sun signed a five year license agreement. Under this agreement Microsoft was allowed to distribute the Sun compiler, runtime, and class libraries and to create new code based on and incorporating Sun copyrighted material. Sun required any new Microsoft code to pass compatibility tests to insure that standard Java programs would run on the Microsoft platform. Periodically Sun could provide new versions of Java and corresponding new compatibility tests.

 

Java 1.0 was essentially a Beta release. Based on testing and feedback, Sun made some important changes to the language (inner classes, Reader and Writer I/O, reflection, RMI, JavaBeans, and a completely new Native Interface) and brought out Java 1.1.

 

Microsoft also updated its Java runtime and tools to support both the structural changes to the language (such as inner classes) and the changes to the class libraries. Nobody doubts that Microsoft's Java runtime fully and compatibly supported the execution of Java 1.1 programs. However, Microsoft claimed that it was not required to ship every new feature that Sun wanted to add to the class library.

 

The problems with Java 1.0 had been clear to everyone. While Sun was busy fixing these problems one way, Microsoft had solved some of them a different way. Whether it was allowed to do that or not depended on how you read the contract. What was certainly clear is that Microsoft and Sun had completely different views of the future of Java.

 

Microsoft regarded Java as just another programming language. It was more sophisticated (with integrated threading and networking) than Visual Basic, yet easier to learn and use than C++. Microsoft expected Java to join the other programming languages in the developer's tool bag. Since the value of any language was determined by the domain of applications it could tackle, Microsoft wanted to make Java the most powerful and flexible language it could be.

Sun, on the other hand, began to regard Java as an application programming platform that would replace all other programming languages and even some operating systems. The original slogan had been "Write once, run anywhere." Over time this drifted into having a second meaning, "Run anywhere, run everywhere." Sun did not want Java to be any more powerful on Windows than it was on all other systems.

If Microsoft had let the conflict develop slowly and naturally, the outcome might have been different. Instead, a few managers decided to pick a fight with Sun. They decided to omit the class libraries for Remote Method Invocation (RMI) and to disable generation of output for the new version of the Java Native Interface (JNI). A customer could not use RMI to communicate between Java programs on Windows and Unix. Similarly, a C language program written to extend Java would not operate correctly in the Microsoft environment.

 

Microsoft could argue that it provided other ways to do the same things. That might be a reasonable defense if Microsoft had been required to do some work to convert these things to Windows. Instead, it was clear that Microsoft had directed its effort to remove features that Sun provided in working form. When the courts ordered Microsoft to restore these features, it took only a week to add them back in.

 

The legal outcome of the subsequent court cases would have been different if Sun only objected to additional useful features added by Microsoft. Instead, the decision by a few managers to intentionally cripple features in their own product also undermined several years of work by dedicated Microsoft programmers. Once the courts uncovered cases of obvious anticompetitive behavior, they were inclined to imagine further problems where none really existed.

 

In retrospect, the most serious mistake made by both companies was to not include an arbitration clause in the 1996 license agreement. The remedy described in the contract was for either side to claim money damages in "a court of competent jurisdiction." Given that the license ran for only five years, and subsequent events show that it takes about five years to bring a case to trial, the courts did not provide an adequate forum for the resolution of any dispute over terms. Instead, the recent history of computer industry litigation has shown that, in the Federal Court system, the term "competent jurisdiction" is an oxymoron.

 

Sun went into Federal court claiming broad copyright control over every aspect of Java. The courts pointed out that Sun had granted Microsoft a license to use its material and that this was a dispute over that contract. So Sun then claimed that its intent under the contract was to preclude Microsoft from doing anything with Java of which Sun did not approve. Some injunctions issued in November 1998 essentially froze all Java development inside Microsoft. The case then dragged on for three years without ever coming to trial. By then, the five year license agreement had expired.

 

Microsoft accepted defeat from Sun's legal maneuvering. In Jan. 2001 it signed a second contract under which it paid Sun $20 million just to be able to continue to distribute its current version of Java long enough to give existing users a chance to convert to something else. Otherwise, Microsoft agreed to have nothing further to do with the Java platform, JVM, or class libraries.

 

Religious Differences

Starting with Version 1.2 ("Java 2"), Sun began to aggressively fill in standard class library interfaces to all the standard and most optional services supplied by an operating system. A Java program obtained database services through JDBC (whether the database was Oracle, DB2, or SQL Server), directory services from JNDI (whether the directory is generic LDAP, Active Directory, or Novell), Cryptography from JCE, and so on. The interfaces remained the same even if their implementation was different on various systems or devices.

 

Microsoft's COM strategy provided a different interface to most of the same services. COM services were available to and could be shared among components written in any language. For example, using the database service named "ADO" a Visual Basic program could select and connect to a database server. It could then pass this connection to a Perl program that would generate a SELECT statement to query the database. The results returned by the query could then be used by a Delphi program to draw conclusions.

 

Sun's lawyers would like to portray Microsoft as a greedy monopolist defending its iron fisted control of the computer industry from a new technological threat. The reality is quite different. There are some parallels between the Microsoft-Sun clash of cultures to the tensions faced by cohesive immigrant groups like Orthodox Jews or Moslems. On one side there is a secular, cosmopolitan melting pot culture that tolerates diversity, but only within a broad agreed set of shared values. Ethnic food is interesting, but we regard arranged marriages are "barbaric". Meanwhile the immigrant group imported a tight cultural and religious set of values that regards the larger secular community as decadent and insists on maintaining the purity of its separate existence.

 

Microsoft had adopted a strategy where each language could have its adherents and special features. Diversity was an important objective. Java, on the other hand, was intended to remain separate, retain its special integrity, and even advocated a slogan of "100% Pure." Each side could plausibly view its own position as enlightened. The first step in understanding the problem is not to impose your own bias and try to pass judgment on who is "right" and "wrong".

 

Component Architecture

Starting with COM and now extending to its .NET Framework, the Microsoft strategy has been to enable a "component architecture". A customer could write a block of code that performed a particular programming or business function in any language he chose. This component could then be stored in a library where it could be used by any other program written in any other language.

 

The most important programming done in corporate America today is not written in any generally recognized programming language. Financial projections and budget decisions are coded in spreadsheets that run under Excel. Load the spreadsheet, plug in some numbers, and the results appear magically in some specific rows and columns. Following traditional software engineering, a company is supposed to hire a systems analyst to convert the logic in the spreadsheet into a "real program" written in a "real programming language." However, if the spreadsheet is well written, an alternative strategy is to put it in a library and let other programs use it directly through services exposed by Excel.

 

Any programming language that has been adapted to COM, including Borland Delphi or ActiveState Perl, can ask Windows to load a copy of Excel as a COM server. It can then ask Excel to load a specific spreadsheet file, then to plug values into specific cells, then recalculate results, and finally report back the new value in other cells.

 

Data in the COM environment is logically shared by all the components written in all the languages. For example, Excel could be loaded by Visual Basic, a Delphi program could then calculate one value and plug it into a specific cell, a Perl program could calculate another value and plug it into a different cell, and the results could be extracted and used by JavaScript logic.

 

When Microsoft licensed Java from Sun, its highest priority was to integrate Java into its overall component architecture. If Microsoft had not done this, it would have essentially been abandoning its entire strategy for future product development. Asking Microsoft to abandon COM (and its successor, the .NET Framework) would be like asking Sun to abandon Unix.

 

To allow Java to participate in this common environment, Microsoft had to make some extensions to Java. Most of the extensions where hidden in comment fields that any other Java compiler would ignore. However, Windows required a different approach to event handling that could only be accomplished with a new keyword, "delegate", that created a special type of class.

 

And 100% Pure Java program that worked on any other version of Java 1.1 also ran on Microsoft's Java. Microsoft did allow someone to write a Java program that only ran on Windows, but this only appeared to be a compatibility problem. Programs that add users or groups to Active Directory or automate the Mail Merge function in Word were only going to run in Windows anyway. Microsoft allowed these programs to be written in Java. Otherwise, the programs would have to be written in VB, Delphi, or JavaScript.

 

J(mumble)

Microsoft was still dedicated to a application development strategy based on components written in many programming languages. Legally, it was now prevented from making the Java platform part of that strategy. However, Microsoft was completely familiar with Java and was not prevented from borrowing any good ideas.

 

Most of the technologies in Java had been around for decades. "Intermediate language" was a feature of UCSD Pascal in the 1970s. Memory management through "garbage collection" was invented in the '50s. Java's contribution was to combine and use these technologies in a new way and demonstrate their ability to solve new problems introduced by the Internet and the Web.

 

Through COM, Microsoft allowed program components written in different languages to talk to each other. However, each language retained its own standard library and runtime support. When a program used a standard language service (write, writeln, put, print, println) it called a different library for each language.

 

Microsoft now proposed to do something radically different. It would start with the basic execution model of the Java Virtual Machine. It would extend that design to include all of the features included in any modern programming language. From this it would create a Common Language Runtime (CLR) that could support all programming languages from the same library. It would then make this specification public, so any other vendor could adapt their programming system to run in the new environment.

 

There are about 60 programming languages that have been adapted to produce Java bytecode and run in the Java Virtual Machine. Such conversions are hampered, however, by the Sun decision to limit its runtime support to the features that were defined in the Java language. For example, Java doesn't have unsigned byte or integer values. Any language whose standard requires bytes to be unsigned integers can't operate in the JVM. Microsoft's Common Language Runtime has all the data types defined by any language.

 

In converting to the CLR, some 1950's languages have to catch up to the new century. Now that every country in the world is interconnected by high speed networks, no programming language can afford to be stuck with plain US ASCII characters. All languages have to adapt to Unicode characters and adopt some level of sensitivity to internationalization.

 

The new Microsoft runtime is called the .NET Framework. Microsoft created versions of Visual Basic and JavaScript that ran in the Framework. It also created a compiler (called "J#", pronounced "J-Sharp") that accepted a program written in the Java syntax but generating output for the Framework instead of a JVM.

 

The .NET Framework and the Java Virtual Machine are two distinct runtime environments. This is what Sun demanded as settlement of its court case. They cannot communicate directly any more, as the old Microsoft JVM was able to do. Of course .NET and Java can exchange data and requests at the highest possible level through Web Services and XML, but that is relatively inefficient and must be reserved for low-volume traffic.

 

The Sandbox

Previous programming languages were compiled to machine instructions for a particular family of CPU chips. For Windows, the compiler would produce instructions for the Intel processor family (386, 486, Pentium). A compiler for the Macintosh would produce instructions for the PowerPC chip.

 

At the machine instruction level, each piece of data in the application is given an address. Different applications run in different "address spaces" so an application cannot access data belonging to the operating system or to another application. However, every library, language, or component that is part of the application shares a common area of data. A program can be written to calculate any or all possible addresses and therefore access any data belonging to any part of the application.

 

System services to open files or connect to network resources can be called by any routine. A conventional program is only limited by the permissions given to the userid under which the program is run.

 

Java programs, and programs written for the .NET Framwork, are not compiled to machine instructions. Instead, the compiler produces code in what is called an "intermediate language". For Java the intermediate language is called "byte code". In .NET it is called MSIL (pronounced "missile"). The program is packaged, distributed, and installed in intermediate language format. Only when it begins to execute does the runtime system translate the intermediate language into real machine instructions.

 

The structure of the intermediate language and the tests made during the final translation insure that the program is well behaved and only uses memory properly. In particular, a routine can only access data that belongs to it or to which it has been granted access by another routine. Programs cannot access arbitrary locations in memory, nor can they run off the end of an array, buffer, or string. If a routine declares data to be "private" it can reasonably expect that other routines will not be able to access the value of that data.

 

This architecture protects program components from each other and protects the system (or a generic hosting application like a browser or Web server) from even malicious code generated by a programmer. Programmers call this environment "the Sandbox" although it is sometimes referred to more accurately (though less sensitively) as "the Padded Cell".

 

The Native Interface

Intermediate language cannot contain calls to the operating system or to any other external service. A "100% Pure Java" program can only call other Java code in the class libraries.

 

Obviously there must be some way for the library classes to eventually call the operating system. In particular, the routines of the java.io.* package have to be able to open files, list directories, and read and write data on disk. The routines of the java.net.* package have to be able to connect to remote hosts and transmit data over the network. Pure Java cannot do this, so Java allows some routines to be implemented in C through the Java Native Interface or JNI.

 

To use JNI, a programmer creates just the signature of a Java function. The function has a name, return data type, and some number of declared arguments. Instead of coding the body of the function, the programmer just adds the keyword "native" to its declaration.

 

When the Java compiler encounters a "native" function, it generates an indication to the JVM that any call to the function should be routed to an external function written in C and stored in a particular DLL. Of course the programmer still has to write the C source. A Java utility processes the output of the compiler and from it generates the skeleton definition of the C program. The programmer must then fill in the skeleton with the actual code.

 

A "100% Pure Java" source file produces only an output *.class file. That file can be stored on disk or zipped up into a JAR archive. It can be installed on hard disk or be fetched on demand across the network. Because it contains only intermediate language, this code runs entirely in the Sandbox.

 

Any source file that includes "native" routines must eventually produce both a *.class file and a DLL. A DLL cannot be downloaded from a Web server. Generally the class file and DLL are both installed on hard disk and they may have to be put in special restricted directories. The DLL files that support standard Java library services (the file services of java.io and the network services of java.net for example) are distributed with the Sun Java runtime are are installed in the \jre\bin subdirectory of the Java install directory.

 

Since JNI starts with Java source, anything produced by this system is Java-friendly. A "native" routine accepts ordinary Java arguments with standard Java data types. This places the burden on the C implementation to translate between the Java data types and any other format the operating system expects to use. On Unix, for example, the Java Unicode String values must typically be converted to null terminated ASCII byte strings to be passed to the operating system, and return values may have to be translated back.

 

Java Isn't Everything

The people at Sun who designed Java came out of the Unix tradition. Unix has its own creation myth. In the 1960s Bell Labs got suckered into a project to create a vast new operating system called Multics. Multics was written in a powerful higher level language called PL/I that contains all the features of all previous languages. Similarly, the operating system was designed with all the features that anyone had ever considered putting in an OS. The resulting mess was too big, too slow, and unusable.

 

The refugees from this disaster regrouped and decided to create a smaller, simpler system. Instead of PL/I, they created a minimal programming language called C. While Multics had many ways to solve a problem, Unix would have only one option for any service you might need. This became the doctrine of "Less is More."

 

Unix was fine when it was used in the environment for which it was originally designed: timesharing on minicomputers. Being small and easy to understand, the core of Unix could also be easily adapted to any single new environment you wanted to support. The problem came after hundreds of separate simple extensions had been developed and people now wanted to integrate them all together. Slowly it became clear that some of the most basic architectural decisions made in Unix were short sighted. The designers at Bell Labs had specifically decided that Unix didn't need multithreading, but in the modern era of network based Web, application, and database servers it is clear that no system can perform properly without threads.

 

Paradoxically, the Unix philosophy "overdid" the idea of Less. The people who designed Java had not yet accepted this criticism. They still believed that "Less is More" was one of the Six Commandments, and that adding additional features to a language is one of the Four Deadly Sins.

 

Anyone is free to impose their personal aesthetics on a language. However, if you intend to claim that your language is the basis for all future computing, then you have to temper your personal preferences with a proper respect for the opinions of all the people who worked long and hard on previous computer languages. Once Sun developers created Java to their own idiosyncratic tastes, they have no right to expect everyone else to convert all programs to it.

 

The most obvious omission was unsigned integers. A more fundamental omission was the "enumeration". Its not just that enumerations are part of every language from Pascal through Ada to C++. They are also basic elements in language-independent interface definition and schema standards.

 

Since there is no direct way to map many existing industry standards into Java, the JNI was designed to put the burden on the other side. It doesn't start with the external standard. You have to start with Java source. You have to define the interface or format in a way that is friendly to Java, then figure out how to do the mapping. The burden is placed on the C code to translate between the external interface and the new Java version.

 

Sun regards this as a feature rather than a problem. The "write once, run anywhere" philosophy encourages anyone seeking to extend the Java programming language to ignore the idiosyncrasies of any particular operating system. Services should be defined in an idealized and Java-centric programming model, preferably beginning with the letter "J" (JDBC, JNDI, JAAS, JAXP). If this interface can only be implemented using native code, then ideally the same interface will be implemented on every operating system using appropriate code native to each system.

 

Automatic Extension on Demand

There are thousands of individual functions in the Windows programming interface, and an unlimited number of COM components. It would be prohibitively expensive to build custom interfaces to each service in advance. The strategy adopted by Microsoft in Visual Basic was to generate the equivalent of a "native" interface on demand for any particular system service or COM component the user might request.

 

The Java standard doesn't preclude automatic generation of native extensions. However, to do this with JNI, a tool would have to analyze the system interface or COM component, perform the mapping from external data types to Java data types, generate the Java source with the "native" keyword, compile it, generate the C source and compile it. If Microsoft had been willing to jump through all these hoops, Sun would have nothing to complain about.

 

However, Microsoft decided that its version of Java would meet everyone else half way. Most of the time the extensions that Microsoft created could be hidden as compiler directives that, from the point of view of Java syntax, were comments. Run through another Java compiler and they would be ignored.

 

However, Java has to be a bit more cooperative when it comes to "callbacks" and "event handling". In many cases the Java program must provide external software with more than parameters. It must also supply routines that the external code can call to signal events, indicate errors, or request additional instructions. Communication between components is a two way street. So Microsoft created a more flexible system in which Java itself had to give a little.

 

Data Structures

Every programming language has a feature that allows a block of related information to be packed together in a single program unit. In different languages these can be called structures, structs, or records. A Java class that contains only variable data fields (and no routines) is almost like a C struct, but it carries some additional baggage that makes it incompatible.

 

Consider the Windows routine GetSystemInfo. It passes back a SYSTEM_INFO data structure. Right now the most interesting variable in the structure is the number of CPUs (in a server or workstation that allows multiple CPUs). Another field in the structure will allow a program to distinguish a system using the new 64-bit Intel Itanium or AMD Opteron CPU chip from one using a conventional 32-bit Pentium or Athlon CPU.

 

/**

* @dll.struct()

*/

public static class SYSTEM_INFO {

public short wProcessorArchitecture;

public short wReserved;

public int dwPageSize;

public int lpMinimumApplicationAddress;

public int lpMaximumApplicationAddress;

public int dwActiveProcessorMask;

public int dwNumberOfProcessors;

public int dwProcessorType;

public int dwAllocationGranularity;

public short wProcessorLevel;

public short wProcessorRevision;

}

So Microsoft created a directive that would allow the compiler to create the same type of data structure used by other languages. The programmer creates a Java class that contains only data fields. In front of the class definition there is a comment statement with the special string "@dll.struct()". This tells the Microsoft compiler to generate a data structure without any of the usual Java object overhead. The program can create an instance of this object, use it to interact with the system, and access the value of the variable fields. It can also be passed as an argument to "native" routines that intend to pass it on, unmodified, to operating system routines that expect a C "struct".

 

Only the Microsoft compiler recognizes this directive. If this code is compiled on any other Java system, the SYSTEM_INFO structure is generated as an ordinary Java class. The program remains valid and produces correct Java. It is unlikely that this part of the program would be useful on other systems, however, because the SYSTEM_INFO structure is only meaningful on Windows.

 

DLL Functions

There already is a GetSystemInfo function in the Windows operating system. It is a C subroutine located in a system DLL. You could create a proper JNI routine to access it. However, once the Java program has created the data structures and types that the routine expects, it is possible to call it directly.

 

/**

* @dll.import("KERNEL32", auto)

*/

public static native void GetSystemInfo(SYSTEM_INFO lpSystemInfo);

This Java source defines a "native" routine called GetSystemInfo that is passed an instance of the SYSTEM_INFO class defined above. The "@dll.import" tells the Java compiler to automatically generate a "native" code linkage to an existing C routine in the KERNEL32.DLL library. The Java programmer doesn't have to run any utilities or write any custom C code. He doesn't even have to know C. The Microsoft compiler does all the work and links things up.

 

If this code is compiled by any other Java compiler, the comment is ignored. The "native" keyword tell the compiler to generate a JNI linkage. The class will not execute until some C language code is generated to resolve the native function.

 

The presence of compiler directives in the comments does not break Java language compatibility. It is unlikely that this code would ever be implemented on other systems, but that is because it calls a Windows system service that doesn't make sense on other systems.

 

Delegate

Over the last decade every Unix vendor has been adding multithreading to the original Unix design. Since threads were an afterthought, they are not part of the interface to any system service. Threads are rather light-weight and interchangeable. Within an application, each thread can do anything another thread can do.

 

Many resources have to be "serialized". This should not come as a surprise to Java programmers, since Java has always had a serialized attribute so that a block of code is executed by only one thread at a time.

 

An alternative design, which has been around since the earliest computer systems, is to assign certain blocks of data or system interfaces to the control of a single thread. If any other code running under a different thread needs access to the resource, it must ask the controlling thread to perform the operation and return the results. This is like asking the teller at the bank to withdraw money from your account rather than just walking into the vault and trying to do it yourself.

 

The original Windows architecture was influenced by a broad view of operating systems and not the narrow and ideological perspective of Unix. Threads were always a part of the Windows design, and it was natural to assign control of some system interfaces to particular threads. When a user interface window is created on the screen, ownership of the window is assigned to the thread that created it. It is up to that thread to populate the window with user interface elements (menus, toolbars, buttons, sliders, and text). If two different threads tried to add or remove user elements in the same window at the same time they could damage the interface. Furthermore, all events generated by user activity in the window (mouse clicks, key strokes) are processed by the thread that owns the window.

 

Similarly, the thread that creates a COM interface to an external component is responsible for all subsequent communication. So when a thread loads an external copy of Excel, only that thread can instruct Excel to load a spreadsheet, plug numbers into the cells, recalculate, and the return the results. [Athough paradoxically a second thread (or another program) can establish a second connection to the same copy of Excel loaded by the first thread. The two threads can concurrently transmit commands to Excel on the two connections. Each thread is still limited to using only the connection it created, even though both connections terminate at the same copy of Excel.]

 

In Java all objects are shared in common by all threads. A button on the user interface or a session to an external program are represented by objects that can be used by any thread. To avoid conflict, elements should be "synchronized" so only one thread uses them at a time.

 

The difference between the two system designs was not something that Microsoft could squeeze in with compiler directives hidden in a comment statement. This required a new keyword to create a new type of object.

 

In Microsoft Java, a "delegate" is a special type of object. The delegate is created by a thread and is associated with a routine that handles events. The delegate is then passed as the callback function or event handler in COM or Windows system services.

 

In Sun Java, an object waits for an event. The object has an event handling routine. When a thread comes along to signal the event, it calls the event handling routine itself. In human terms, it is as if a hotel guest walked up to the Bell Captain's desk looking for help with luggage, rang the bell (signaling the event), then changed into a bellhop uniform to put the luggage on the cart and carry it to the room, returned to the Bell Captain's desk, changed back to the original clothes, and then proceeded to the room as a guest.

 

Under Microsoft's extensions to Java, the delegate waits for the event. When the delegate is triggered, the calling thread is temporarily suspended while the event handling routine runs under the thread that created the delegate object. In this version of the previous example, the guest rings the bell. A bellhop (thread) waiting at the desk takes the luggage up to the room while the guest waits. The bellhop returns to the desk to wait for another request, and this releases the waiting guest to follow his luggage up to the room.

 

The idea that particular threads wait on events has been part of operating system designs since the first IBM mainframe operating systems in 1965. It was a basic feature of the multithreaded design of the Ada programming language. Only a narrow minded dedication to the philosophy of "Less is More" combined with the observation that Sun's own Solaris operating system doesn't need this feature can explain the omission of the delegate (or an equivalent concept) from the Java standard.

 

Variant

Java is a "strongly typed" and compiled language. The Java programmer declares the type of each variable. An integer variable can be assigned a value of 365, a floating point variable can be assigned 3.14159, and a String variable can be assigned the value "a priest, a barber, and a horse walk into a bar ..."

 

Other languages (notably JavaScript, REXX, and Perl) are weakly typed and interpreted. Any variable can be assigned any number or string value. The type of the value isn't checked until it is used. If it is used as a number, it better be a number or something that can be converted to one.

 

Excel spreadsheet cells are an obvious example of weak typing. You can enter numbers or text into a cell. Excel doesn't care if a cell has text as long as the cell ID is not used in the formula that calculates a value for another cell.

 

If Java is to interoperate through COM with these other languages and applications, then it needed a generic object that can hold all types of data. Microsoft added a Variant class it its library. A Variant is an Object that can contain values that are integer, float, string, or boolean. Such a structure is not unprecedented. JDBC ResultSet objects encapsulate the column variables returned from a query. Each column can be fetched in various formats (getInt, getLong, getDate, getString). Variants and the classes that support them serve no useful purpose for a pure Java program, but they help to bridge the gap between Java and the other languages that cannot make up their mind about how to treat data.

 

The Judges Just Don't Get It

Microsoft wanted Java to be the best possible language, as defined by its language architecture. Sun had a different point of view. The Sun perspective didn't become objectively the "right" criterion just because Sun invented Java, or because Microsoft has monopoly power in PC operating systems. Instead, both vendors are right.

 

The two versions of Java can be installed on any machine. They contain no conflicting components. You run the Sun compiler with "javac" and the Microsoft compiler with "jvc". You run a Java program under the Sun runtime with the "java" command and under the Microsoft runtime with the "jview" command. The decision to use one version of Java or the other is made application by application. The programmer may force a selection, or it may be left to the user who runs the program.

 

It is not, however, just a choice between Sun and Microsoft. Specific applications are distributed with a particular Java runtime because they have been designed for a particular configuration. A program may require JRE 1.3.1 or 1.4.0. IBM has its version of the Java runtime. Oracle distributes different versions of Java with the database, application server, and application clients.

 

All of these versions of Java are "right" for a user who needs that particular collection of features. The Microsoft JVM is the only choice if you want to use Java to control and automate an Excel operation. The Sun or Microsoft JVM are needed to get current class libraries like the "collections" framework.

 

What is clearly wrong by any measure is to deny programmers the right to make their own decision to select the best tool for the application they are designing. Yet that is the thrust of the Sun legal effort and it has been endorsed by every Judge to who the case has been presented. Any careful analysis of judicial opinions in these matters, however, make it clear that none of these Judges has ever really understood the technology, how it works, why it was created, or what it is used for. Consider the bizarrely one-sided and technically incoherent description generated by Judge Jackson in his findings in the Federal antitrust case:

 

In a further effort intended to increase the incompatibility between Java applications written for its Windows JVM and other Windows JVMs, and to increase the difficulty of porting Java applications from the Windows environment to other platforms, Microsoft designed its Java developer tools to encourage developers to write their Java applications using certain "keywords" and "compiler directives" that could only be executed properly by Microsoft's version of the Java runtime environment for Windows. [394 in Findings of Fact]

 

Microsoft certainly created keywords and directives. As was previously pointed out, the compiler directives were buried in comment fields that are ignored by other Java compilers, and any failure of the program to run on other systems was due to the intentional use of a Windows system service and not due to a reaction of the other system to the directive. They delegate keyword would generate a syntax error on other systems, but again this is only used when you are talking to a COM component that doesn't run on any other system.

 

The Microsoft extensions allowed programmers who wanted to write Windows-only programs to write them in Java. If the extensions were not provided by Microsoft, these programs would have been written in Visual Basic or Delphi. They could never be written in 100% pure Sun Java.

 

Was this War Really Necessary?

In its most recent court case, Sun portrays a conflict between Java and the .NET Framework for "mindshare" in the developer community. This is a two horse race that will decide the future of the industry.

 

Competition is good. We who use and develop applications within the technology benefit when there are two alternatives each with strengths and weaknesses. However, the advantage of choice disappears when we are asked to convert 100% of our development to ether alternative.

 

Microsoft has the most general solution and a very powerful collection of initial building blocks. The strength of this offering, however, is compromised by the same poor management decisions that got Microsoft in trouble over Java. Whenever Microsoft has an offering in any area of technology, they target their development specifically to their own product and often fail to support generic standards. Because Microsoft's Active Directory is based on the LDAP protocol, for example, Microsoft programming technology fails to operate correctly with any other LDAP server. Microsoft support for Exchange similarly drives out any support or testing of other E-Mail standards. Java has much better support for industry-wide standards.

 

Java and the .NET Framework will continue to interoperate. The emerging technology of Web Services guarantees a high level component architecture where both platforms can exchange data and requests. This will be adequate for some purposes, but it is not efficient.

 

Competition is good, War is bad. It is particularly bad for the civilians who get caught in the middle. Microsoft may have instigated the war with its silly provocative decisions on RMI and JNI. Sun then initiated formal hostilities. The fighting may have cooled off some in recent months, but now the innocent programmers in other companies and universities must deal with the scorched earth that was left behind.

 

If Microsoft had been allowed to continue Java development, we can project their previous work onto the current technology. They would have been able to update their Java runtime to support current generation class libraries (collections, internationalization, etc.). Microsoft might have updated Java's COM support to also include .NET Remoting for high performance interoperability with components written in other languages. Then people could write in any language, on any platform, with any services they chose.

 

Instead, there is a wall between Java and .NET that cannot easily be scaled. You have to decide to use either Java or .NET technology. The only communication between the two is provided by Web Services. This complicates program design, creates two distinct sets of programming skills, and fragments any libraries of tested reusable components.

 

 

Jos jedno:

 

 

 

Home -> Why Java Will Always Be Slower than C++

 

Why Java Will Always Be Slower than C++

by Dejan Jelovic

 

 

 

"Java is high performance. By high performance we mean adequate. By adequate we mean slow." - Mr. Bunny

 

 

 

Anybody that has ever used a non-trivial Java program or has programmed in Java knows that Java is slower than native programs written in C++. This is a fact of life, something that we accept when we use Java.

 

However, many folks would like to convince us that this is just a temporary condition. Java is not slow by design, they say. Instead, it is slow because today's JIT implementations are relatively young and don't do all the optimizations they could.

 

This is incorrect. No matter how good the JITs get, Java will always be slower than C++.

 

The Idea

People who claim that Java can be as fast as C++ or even faster often base their opinion on the idea that more disciplined languages give the compiler more room for optimization. So, unless you are going to hand-optimize the whole program, the compiler will do a better job overall.

 

This is true. Fortran still kicks C++'s ass in numeric computing because it is more disciplined. With no fear of pointer aliasing the compiler can optimize better. The only way that C++ can rival the speed of Fortran is with a cleverly designed active library like Blitz++.

 

However, in order to achieve overall results like that, the language must be designed to give the compiler room for optimization. Unfortunately, Java was not designed that way. So no matter how smart the compilers get, Java will never approach the speed of C++.

 

The Benchmarks

Perversely, the only area in which Java can be as fast as C++ is a typical benchmark. If you need to calculate Nth Fibonacci number or run Linpack, there is no reason why Java cannot be as fast as C++. As long as all the computation stays in one class and uses only primitive data types like int and double, the Java compiler is on equal footing with the C++ compiler.

 

The Real World

The moment you start using objects in your program, Java looses the potential for optimization. This section lists some of the reasons why.

 

1. All Objects are Allocated on the Heap

Java only allocates primitive data types like int and double and object references on the stack. All objects are allocated on the heap.

 

For large objects which usually have identity semantics, this is not a handicap. C++ programmers will also allocate these objects on the heap. However, for small objects with value semantics, this is a major performance killer.

 

What small objects? For me these are iterators. I use a lot of them in my designs. Someone else may use complex numbers. A 3D programmer may use a vector or a point class. People dealing with time series data will use a time class. Anybody using these will definitely hate trading a zero-time stack allocation for a constant-time heap allocation. Put that in a loop and that becomes O (n) vs. zero. Add another loop and you get O (n^2) vs. again, zero.

 

2. Lots of Casts

With the advent of templates, good C++ programmers have been able to avoid casts almost completely in high-level programs. Unfortunately, Java doesn't have templates, so Java code is typically full of casts.

 

What does that mean for performance? Well, all casts in Java are dynamic casts, which are expensive. How expensive? Consider how you would implement a dynamic cast:

 

The fastest thing you could do is assign a number to each class and then have a matrix that tells if any two classes are related, and if they are, what is the offset that needs to be added to the pointer in order to make the cast. In that case, the pseudo-code for the cast would look something like this:

 

DestinationClass makeCast (Object o, Class destinationClass) {

Class sourceClass = o.getClass (); // JIT compile-time

int sourceClassId = sourceClass.getId (); // JIT compile-time

 

int destinationId = destinationClass.getId ();

 

int offset = ourTable [sourceClassId][destinationClassId];

 

if (offset != ILLEGAL_OFFSET_VALUE) {

return <object o adjusted for offset>;

}

else {

throw new IllegalCastException ();

}

}

Quite a lot of code, this little cast! And this here is a rosy picture - using a matrix to represent class relationships takes up a lot of memory and no sane compiler out there would do that. Instead, they will either use a map or walk the inheritance hierarchy - both of which will slow things down even further.

 

3. Increased Memory Use

Java programs use about double the memory of comparable C++ programs to store the data. There are three reasons for this:

 

Programs that utilize automatic garbage collection typically use about 50% more memory that programs that do manual memory management.

Many of the objects that would be allocated on stack in C++ will be allocated on the heap in Java.

Java objects will be larger, due to all objects having a virtual table plus support for synchronization primitives.

A larger memory footprint increases the probability that parts of the program will be swapped out to the disk. And swap file usage kills the speed like nothing else.

 

4. Lack of Control over Details

Java was intentionally designed to be a simple language. Many of the features available in C++ that give the programmer control over details were intentionally stripped away.

 

For example, in C++ one can implement schemes that improve the locality of reference. Or allocate and free many objects at once. Or play pointer tricks to make member access faster. Etc.

 

None of these schemes are available in Java.

 

5. No High-Level Optimizations

Programmers deal with high-level concepts. Unlike them, compilers deal exclusively with low-level ones. To a programmer, a class named Matrix represents a different high-level concept from a class named Vector. To a compiler, those names are only entries in the symbol table. What it cares about are the functions that those classes contain, and the statements inside those functions.

 

Now think about this: say you implement the function exp (double x, double y) that raises x to the exponent y. Can a compiler, just by looking at the statements in that function, figure out that exp (exp (x, 2), 0.5) can be optimized by simply replacing it with x? Of course not!

 

All the optimizations that a compiler can do are done at the statement level, and they are built into the compiler. So although the programmer might know that two functions are symmetric and cancel each other now, or that the order of some function calls is irrelevant in some place, unless the compiler can figure it out by looking at the statements, the optimization will not be done.

 

So, if a high-level optimization is to be done, there has to be a way for the programmer to specify the high-level optimization rules for the compiler.

 

No popular programming language/system does this today. At least not in the totally open sense, like what the Microsoft's Intentional Programming project promises. However, in C++ you can do template metaprogramming to implement optimizations that deal with high-level objects. Temporary elimination, partial evaluation, symmetric function call removal and other optimizations can be implemented using templates. Of course, not all high-level optimizations can be done this way. And implementing some of these things can be cumbersome. But a lot can be done, and people have implemented some snazzy libraries using these techniques.

 

Unfortunately, Java doesn't have any metaprogramming facilities, and thus high-level optimizations are not possible in Java.

 

So...

Java, with the current language features, will never be as fast as C++. This pretty much means that it's not a sensible choice for high-performance software and the highly competitive COTS arena. But its small learning curve, its forgiveness, and its large standard library make it a good choice for some small and medium-sized in-house and custom-built software.

 

 

 

 

 

Notes

1. James Gosling has proposed a number of language features that would help improve Java performance. You can find the text here. Unfortunately, the Java language has not changed for four years, so it doesn't seem like these will be implemented any time soon.

2. The most promising effort to bring generic types to Java is Generic Java. Unfortunately, GJ works by removing all type information when it compiles the program, so what the execution environment sees is the end is again the slow casts.

 

3. The Garbage Collection FAQ contains the information that garbage collections is slower than customized allocator (point 4 in the above text).

 

4. There is a paper that claims that Garbage Collection Can Be Faster than Stack Allocation. But the requirement is that there is seven times more physical memory than what the program actually uses. Plus, it describes a stop-and-copy collector and doesn't take concurrency into account. [Peter Drayton: FWIW, this is an over-simplification of the paper, which provides a means of calculating what the cross-over point is, but doesn't claim that 7 is a universal cross-over point: it is merely the crossover point he derives using the sample inputs in the paper.]

 

 

 

 

 

Feedback

I received a lot of feedback about this article. Here are the typical comments, together with my answers:

 

"You forgot to mention that all methods in Java are virtual, because nobody is using the final keyword."

 

The fact that people are not using the final keyword is not a problem with the language, but with the programmers using it. Also, virtual functions calls in general are not problematic because of the call overhead, but because of lost optimization opportunities. But since JITs know how to inline across virtual function boundaries, this is not a big deal.

 

Java can be faster than C++ because JITs can inline over virtual function boundaries.

 

C++ can also be compiled using JITs. Check out the C++ compiler in .NET.

 

In the end, speed doesn't matter. Computers spend most of their time waiting on our input.

 

Speed still maters. I still wait for my laptop to boot up. I wait for my compiler. I wait on Word when I have a long document.

 

I work in the financial markets industry. Sometimes I have to run a simulation over a huge data set. Speed matters in those cases.

 

It is possible for a JIT to allocate some objects on a stack.

 

Sure. Some.

 

Your casting pseudo-code is naive. For classes a check can be made based on inheritance depth.

 

First, that's only a tad faster than the matrix lookup.

 

Second, that works only for classes, which make up what percentage of casts? Low-level details are usually implemented through interfaces.

 

So we should all use assembly, ha!?

 

No. We should all use languages that make sense for a given project. Java is great because it has a large standard library that makes many common tasks easy. It's more portable than any other popular language (but not 100% portable - different platforms fire events at different times and in different order). It has garbage collection that makes memory management simpler and some constructs like closures possible.

 

But, at the same time, Java, just like any other language, has some deficiencies. It has no support for types with value semantics. Its synchronization constructs are not efficient enough. Its standard library relies on checked exceptions which are evil because they push implementation details into interfaces. Its performance could be better. The math library has some annoying problems. Etc.

 

Are these deficiencies a big deal? It depends on what you are building. So know a few languages and pick the one that, together with the compiler and available libraries, makes sense for a given project.

Share this post


Link to post
Share on other sites

  • Replies 62
  • Created
  • Last Reply

Top Posters In This Topic

@Gospodin Graul

 

 

Ako si imao strpljenja da procitas prvi deo onog baje sa Yale-a, vidis verovatno dilemu. Meni se vise svidelo razmisljanje Majkrosofta, strogo u tehnickom smislu. Imas JavaWorld.com recimo neko realno vidjenje u tom trenutku, ali se od drveta ne vidi suma. Neverovatno je da ovi ljudi nisu seli da se dogovore sta i kako. Uspesno.

 

 

Meni je jezivo spora Sun-ova Virtualna Masina a to ti je sad jedino ostalo. Majkrosoft je to bio tako krasno optimizovao, milina. Cak su imali i nativni znaci x86 kompajler. Ej bre. Mislim, ej. Marmot se taj projekat zvao. Sve uspeli da spakuju u onaj svoj portabilni egzekutabilni format (PE-32) i to u binarnom obliku, znaci ne koristi uopste virtualnu masinu, standardni Windows .exe file to sve bude. Jedino im je falila ta RMI (Remote Method Invocation) podrska, ali i to bi frajeri odradili nekako. Puce sve. Ali umesto svih tih lepih stvari, rodio se .NET koji naravno kida. No to je neka druga tema.

Share this post


Link to post
Share on other sites

Pa dobro, ja ionako smatram Javu za neku vrstu specijalnog programa sa svim svojim specijalnim manama i specijalnim osobinama (moje amatersko mišljenje). Ovde u Srbiji se do jaja traži posao Java programera, verovo il ne, evo kladionica Mozzart izbacila oglas ( inače jedna od najvećih u Srbiji, mogu misliti kolka je plata). Dakle, Java nije klasika ko eto C++, al nekako nalazi svoju primenu. Jedino kad kažem da je Java budućnost, mislim na to da će sa sve bržim i bržim kompovima brzina postati manji problem, .... ma videćemo. Ko što svi koji brane Vistu kažu slično :) Tehnologija se stalno menja, ne može se sve uvek predvideti... kao što rekoh Java, kao i svaki drugi program će uvek naći svoju primenu.

 

Kolko sam ja razumeo , Majkrosoft je hteo da zbudži Javu da može samo na Windowsu da se koristi, u stvari da brže radi kao takva na Windowsu nego u običnom JAVA rantajmu... znaš to je ipak kršenje neke vrste slobode, na duže staze možda se pokaže da je Sun bio u pravu... a možda i ne, ipak slažem se da je Sun načinio rizičan potez.

Edited by Господин Граул

Share this post


Link to post
Share on other sites

Ode tema u off.

Java programeri su sve trazeniji, kako kod nas tako i u svetu. Jbg, princip "pisi jednom izvrsavaj bilo gde" nije mala stvar pogotovo kad ne znas koji ce ti OS u kom trenutku biti instaliran, a doticna Java nam bas to omogucava. Inace kada sam malo uzeo da pogledam C#, shvatio sam da je Microsoft iskopirao Javinu foru resavanja problema ( ne mislim na platformsku nezavisnost posto to ne pruza) i resio da to naplati.

A te sajtove popularnosti ne treba uzimati kao nikakvo merilo jer se to steluje kako kome odgovara. Bacite pogled na ponudu poslova i sta se trazi i samo tako cete videti sta je trazeno. Ja koliko sam u video dosta aplikacija za firme se radi u Java, naravno radi se i u ostalim jezicima ali najvise u Java za sada.

Back on Topic ljudi!

Edited by R_a_S_a

Share this post


Link to post
Share on other sites

Evo vam jedne moje animacije za početak, pa ako vam se sviđa, recite, da okačim još poneku. :)

 

 

Cheers. :)

 

znam za ovu animaciju od ranije, valjda sam je nasao na netu i bas me je iznenadila jer ne izgleda uopste lose. jesi li presao na 64-bitan 3d softver, trebalo bi da radi dosta brze?

Share this post


Link to post
Share on other sites

znam za ovu animaciju od ranije, valjda sam je nasao na netu i bas me je iznenadila jer ne izgleda uopste lose. jesi li presao na 64-bitan 3d softver, trebalo bi da radi dosta brze?

 

tnx. :)

 

Nisam prešao na 64-bitan software, pošto mi još uvek nije bitan. :)

Ja sam ti više old-school, radim još uvek u max-u 7, iako imam core2duo procesor.

Ima vremena za 64 bita. :)

 

Evo ga još jedan rad (konkurs na forumu sveta kompjutera, tema je: screenshot iz video igre; osvojio prvo mesto).

 

Sacred Town:

Share this post


Link to post
Share on other sites

" Sun did not want Java to be any more powerful on Windows than it was on all other systems " :icon_question: Na to sam mislio.

 

Nema problema na sta god da si mislio. U tome je i najveca greska Sun-a. Jel neko uopste procitao ceo clanak? MS nije nista izmenio (sem sto su izostavili u jednom trenutku pa vratiliza nedelju dana JNI i RMI interfejse, posto su se prvo malo sprdali na Sun-ov racun, tojest malo ih provocirali). MS je dodao par stvari ali samo na Win platformi. Ako koristis taj isti source kod na drugoj platformi, kompajliran bilo MS bilo nekim drugim, trecim kompajlerom, i ne ubacis te dve nove direktive, sve je identicno. Znaci, samo postoji plus na Win platformi, sto ne znaci da su druge u minusu (mada su Sun inzenjeri verovatno to tako videli). Na kraju je MS, kako spomenuh, krenuo da radi NATIVNI kompajler za Javu cijom upotrebom (na Windows platformi) bi izbegao Java Virtualnu masinu i ubrzao egzekuciju visestruko, da ne kazem 'reda velicine'. 10 puta, mozda i 100 puta. JVM je rak rana Sun-ova (na Java kao jezicka specifikacija vec sama virtualna masina). CLR sa sve .NET framework-om, koji je mnogo puta veci nego Sun-ove klasne biblioteke , radi mnogo brze u svim elementima igre. Pocev od GUI, preko OS poziva sve do konekcija i manupilisanja bazama podataka.

Edited by Elam Harnish

Share this post


Link to post
Share on other sites

  • 1 month later...
sto se softvera generalno tice, sve vise SW developera uvodi podrsku za GPU racunanje (Adobe za iduci PS recimo..il sljedeci Mac OS)..bas je bila zanimljiva debata na jednoj od prije spomenutih konferencija na temu CPU vs. GPU od strane ekipe iz Intela, nVIDIAe i AMDa..

Stvari se napokon pomiču s mrtve tačke:

http://www.tcmagazine.com/comments.php?sho...442&catid=3

Share this post


Link to post
Share on other sites

  • 1 year later...

da ne otvaram novu temu konkretno za ovo, pitacu ovdje:

 

trebala bi mi hitno mala pomoc oko ccmalloc-a. trazih na netu da skinem al ne nadjoh pa ako neko ima link bila bih zahvalna da mi proslijedi.takodje bi mi trebale neke kratke upute kako se koristi. trebala bih provjeriti memory leakove u programu u c++ (koristim trenutno DEV C++ jer mi nije visual studio instaliran). ako imate kakvu drugu preporuku za program za detekciju leakova, meni je svejedno,ne mora nuzno ccmalloc.

 

 

takodje, ima li ko neki sazetiji primjer CFG fajla da po uzoru na to napisem svoj.malo sam u frci zbog dokumentacije,pa bi mi koristilo nesto takvo.

 

 

i da,da bih ErrorLog fajl (svoj) napravila da bude singleton treba da deklarisem funkciju synchronized?

 

 

hvala unaprijed na pomoci,nadam se brzim odgovorima haha(:

Edited by selma

Share this post


Link to post
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...