JSR-045规范

 

JSR-045是针对非Java语言,需要编译成class文件在JavaVM上运行并调试的一个规范。

以下内容来自:http://jcp.org/aboutJava/communityprocess/review/jsr045/index.html

 


JSR-045: Debugging Support for Other Languages

 


Goal
Terminology
Approach
     Single Translation
      Multiple Translations
     Diagram
Scope
     Variables
     Multi-Level Source View
     Finding Source
     Multiple Source Files per Class File
Source Map
     General Format
     Header
     StratumSection
     FileSection
     LineSection
     VendorSection
     EndSection
     EmbeddedSourceMaps
     SMAP Syntax
SMAP Resolution
     LineInfo Composition Algorithm
     Resolution Example
JPDA Support
SourceDebugExtension Support
     SourceDebugExtension Access
     SourceDebugExtension Class File Attribute
Example
     Input Source
     Language Processor
     Post Processor
     Debugging
License


Goal

A mechanism is needed by which programs executed under the JavaTM virtual machine but written in languages other than the Java programming language, can be debugged with references to the original source (for example, source file and line number references).

Constraints:

  • No change to the Java programming language.
  • Optional change to Java programming language compiler.
  • No change to JPDA clients (debuggers, ...) for basic functionality. With the exception being, tools that arbitrarily prohibit non-Java programming language source.
  • Minimal change to Java virtual machine.
  • No change to the Java platform class libraries.


Terminology

 

TermDefinition
final-source The final form of source. This source will be compiled into a class file . Typically, final-source is Java programming language source.
translated-source Source that will be translated by a language-processor into another language or form.
language-processor Converts translated-source to final-source or to different translated-source .
class file A collection of bytes in Java virtual machine class file format.
compiler Compiler which converts final-source to class files. For example, javac is a compiler.
post-processor Takes a class file and a Source Map File as input; generates a class file as output. Inserts a SourceDebugExtension attribute .
Source Map
SMAP
Specifies the mapping of source between one or more sets of input source and the output source. See: Source Map Format .
Source Map File
SMAP-file
Specifies the mapping created by a language-processor between translated-source input and the resultant output source. It is a Source Map stored in a file in Source Map Format .
stratum A view of a class from a particular, named, programming language level.
JPDA The Java Platform Debugger Architecture .
JDI The Java Debug Interface, which is the high-level Java programming language interface of the Java Platform Debugger Architecture . See: JDI Specification .
SourceDebugExtension
attribute
A Java virtual machine class file attribute that holds information about the source. In this case, the information is a Source Map in Source Map Format . The source is mapped to final-source (output source). The Source Map has potentially multiple sets of input source (strata ). See: SourceDebugExtension Class File Attribute


Approach

Single Translation

A language-processor translates translated-source to final-source (the case of translation from one translated-source to another translated-source, is addressed below ). It also creates a second output, an SMAP-file , whose format is described in Source Map Format . This file describes the mapping between input source and output source (e.g. line number and source file).

The final-source generated by the language-processor is compiled by the compiler .

The post-processor takes the class file generated by the compiler and the SMAP-file as input. A SourceDebugExtension attribute containing the SMAP in the SMAP-file is added to the class file and the new class file is written.

Optionally, the compiler may take both final-source and the SMAP-file as input, and perform both compilation and installation of the SourceDebugExtension.

When the resultant program is debugged using a debugging tool based on the Java Debug Interface (JDI ) of JPDA , the final-source line number information is converted to the specified language view (strata ).

Multiple Translations

A language-processor might translate source into source which will become input to another language-processor, and so on. Eventually, after possibly many translated-source forms, final-source is produced. Each translation produces SMAP information. This information must be preserved and placed in context, so that each stratum can be mapped to the final-source.

A language-processor checks for an SMAP-file in a location parallel to that of the input source. For example, if the source repository is a file system and the input source is located at path name . extension then path name . extension .smap will be checked for an SMAP. The input SMAPs will be copied into the generated SMAP. See OpenEmbeddedSection for specifics on the embedding of input SMAPs.

In the case of multiple translations, the post-processor must resolve the embedded SMAPs. See SMAP Resolution .

Note that final-source need not be Java programming language source, as compilers for other languages may directly generate class files, including the SourceFile and LineNumberTable class file attributes. SMAPs and the mechanism presented here are still useful for handling multiple translations.

A programming language implementor, directly generating class files might also choose to generate SMAPs (thus functioning as both language-processor and compiler) since the SMAP is useful for describing source configurations (such as multiple source files per class file) which cannot be represented with the SourceFile and LineNumberTable attributes. In this case, the input is translated-source and the final-source is represented in the attributes but is never generated.

Diagram

This diagram demonstrates data flow. The particular case shown has two levels of translation, with file inclusion on the second level (as is the case in the example in SMAP Resolution ).

                                                                                                   
         |  TS0a                          |  TS0b      
         |                              |          
language-processor0
           
language-processor0
    |          |                    |          |     
    |  TS1a      |  SMAP1a                |  TS1b      |  SMAP1b
    |          |                    |          |     
language-processor1
                   |          |                    
                   |  FS     |  SMAP2                     
                   |          |                    
               
compiler
     |                    
                   |          |                    
                   |  class file|                         
                   |          |                    
               
post-processor
               
                        |                         
                        |  class file               
                        |                         
               
Java virtual machine
               
                   |          |                    
                   |  FS location  |  SMAP via SourceDebugExtension     
                   |          |                    
               
JPDA
               
                        |                         
                        |  TS location               
                        |                         
               
debugger application
               

Where TS is translated-source and FS is final-source .


Scope

Variables

The complexity of mapping semantics (like variable and data views) across languages has been discussed. And it has been agreed that this issue will wait for a possible subsequent JSR.

Multi-Level Source View

The ability to choose the source level to view is addressed in this JSR. These are referred to as strata .

Finding Source Files

Currently, final-source is found by combining the follow elements:

  • A source path
  • The package name converted to a directory path
  • The source file name from a JDI call (derived from the SourceFile class file attribute

Since existing debuggers use this mechanism (the only way for an existing debugger to find translated-source ) each aspect must be addressed:

  • The source path must be set-up to include translated-source directories
  • Source must be placed in a directory corresponding to the package
  • The JDI call must return the translated-source name.

For debuggers written against the new APIs, a new method has been added which returns the source path - this makes the translated-source directory structure flexible.

Multiple Source Files per Class File

When an inclusion mechanism is used, a class file will contain source from multiple translated-source files. The SourceFile attribute of class files only associates one source file with a class file which is one reason the approach of simply rewriting the SourceFile and LineNumberTable attributes had to be abandoned. The SMAP allows a virtually unlimited number of source files per stratum.


Source Map Format

A Source Map (SMAP) describes a mapping between source positions in an input language ( translated-source ) and source positions in a generated output language. A view of the source through such a mapping is called a stratum . The SMAP-file contains an unresolved SMAP. The SourceDebugExtension class file attribute, when used as described in this document, contains an SMAP. The SMAP stored in a SourceDebugExtension attribute must be resolved , and thus will have no embedded SMAPs and will have the final-source language as the output language.

An SMAP consists of a header and one or more sections of mapping information.

There are currently seven types of section: stratum sections, file sections, line sections, vendor sections, end sections, and open and close embedded sections. New section types may be added in the future - to facilitate this, any unknown sections must be ignored without error.

The semantics of each section is discussed below. For clarity, an informal description of the syntax of each section is included in the discussion. See the formal SMAP syntax for syntax questions.

General Format

The SMAP consists of lines of Unicode text, with a concrete representation of UTF-8 . Line termination is with line-feed, carriage-return or carriage-return followed by line-feed. Because SMAPs are included in class files, size of the SMAP was an important constraint on the format chosen for them.

Header

The first line of an SMAP is the four letters "SMAP " which identifies it as an SMAP. The next line is the name of the generated file. This name is without path information (and thus if the generated file is final-source, the name should match the SourceFile class file attribute). The last line of the header is the default stratum for this class. The default stratum is the stratum used when a debugger does not explicitly specify interest in another stratum. In an unresolved SMAP the default stratum can be unspecified (blank line). In a resolved SMAP the default stratum must be specified. A specified stratum must either be one represented with a stratum section or "Java " which indicates the standard final-source information should be used by default.

StratumSection

An SMAP may map more than one translated-source to the output source (the output source is final-source if the SMAP is in a SourceDebugExtension ). A view of the source is a stratum (whether viewed as translated-source or final-source). Each translated-source language should have its own stratum section with a unique stratum name. The final-source stratum (named "Java ") is created automatically and should not have a stratum section. The stratum section should be followed by a file section and a line section which will be associated with that stratum.

The format of the section is simply the stratum section marker "*S " followed by the name of the stratum. The section ends with a line termination. One FileSection and one LineSection (in either order) must follow the StratumSection (before the next StratumSection or the EndSection ). One or more VendorSection s may follow a StratumSection. There must be at least one StratumSection .

FileSection

The file section describes the translated-source file names. Each line maps a file ID to a source name and, optionally, to a source path. File IDs are used only in the LineSection . The source name is the name of the translated-source. The source path is the path to the translated-source, the "/" symbol is translated to the local file separator. In the case where the source repository is a file system, source name is the file name (without directory information) and source path is a path name (often relative to one of the compilation source paths). For example: Bar.foo would be a source name, and here/there/Bar.foo would be a source path. The first file line denotes the primary file.

The format of the file section is the file section marker "*F " on a line by itself, followed by file information. File information has two forms, source name only and source name / source path. The source name only form is one line: the integer file ID followed by the source name. The source name / source path form is two lines: a plus sign "+ ", file ID, and source name on the first line and the source path on the second. The file ID must be unique within the file section. A FileSection may only occur after a StratumSection . The FileName must have at least one character. The AbsoluteFileName , if specified, must have at least one character.

For example:

*F
+ 1 Foo.xyz
here/there/Foo.xyz
2 Incl.xyz

declares two source files. File ID #1 has source name "Foo.xyz " and source path "here/there/Foo.xyz ". File ID #2 has source name "Incl.xyz " and a source path to be computed by the debugger.

LineSection

The line section (LineSection ) associates line numbers in the output source with line numbers and source names in the input source.

The format of the line section is the line section marker "*L " on a line by itself, followed by the lines of LineInfo . Each LineInfo has the form:

InputStartLine # LineFileID , RepeatCount : OutputStartLine , OutputLineIncrement

where all but

InputStartLine : OutputStartLine

are optional.

A range of output source lines is mapped to a single input source line. Each LineInfo describes RepeatCount of these mappings. OutputLineIncrement specifies the number of lines in the output source range; this line increment is applied to each mapping in the LineInfo . The source file containing the input source line is specified by LineFileID via the FileSection .

 

 

More precisely, for each n between zero and

RepeatCount


 - 1

the input source line number

InputStartLine


 + n


maps to the output source line numbers from

OutputStartLine


+ (n
* OutputLineIncrement


)

through

OutputStartLine


+ ((n
+ 1) * OutputLineIncrement


) - 1

If absent RepeatCount and OutputLineIncrement default to one. If absent LineFileID defaults to the most recent value (initially zero).

The first line of a file is line one. RepeatCount is greater than or equal to one. Each LineFileID must be a file ID present in the FileSection . InputStartLine is greater than or equal to one. OutputStartLine is greater than or equal to one. OutputLineIncrement is greater than or equal to zero. A LineSection may only occur after a StratumSection .

For example:

      *L
      123:207
      130,3:210
      140:250,7
      160,3:300,2

 

Creates this mapping

Input SourceOutput Source
LineBegin LineEnd Line
123207207
130210210
131211211
132212212
140250256
160300301
161302303
162304305

Note that multiple LineInfo may map multiple input source lines to a single output source line, when such a LineSection is being used to map output source lines to input source lines, a first matching LineInfo rule applies.

Note also that multiple LineInfo may map a single input source line to a multiple, possibly disjoint, output source lines, when such a LineSection is being used to map input source lines to output source lines, a first matching LineInfo rule again applies.

VendorSection

The vendor section is for vendor specific information.

The format is "*V " on the first line to mark the section. The second line is the vendor ID which is formed by the same rules by which unique package names are formed in the Java language specification, second edition (?7.7) Unique Package Names . It includes the following lines until another section marker.

EndSection

The end section marks the end of an SMAP, it consists simply of a "*E " marker. The end section must be the last line of an SMAP.

EmbeddedSourceMaps

The OpenEmbeddedSection marks the beginning and CloseEmbeddedSection the end of a set of EmbeddedSourceMaps . These SMAPs correspond to the input source for a language-processor. The stratum of the language-processor is indicated on both sections. These sections must not occur in a resolved SMAP.

The format is the "*O " marker and the name of the output stratum on the first line. This is followed by the set of embedded SMAPs. The embedded SMAPs are included "whole" - from the SMAP to the EndSection "*E " marker - inclusive. Finally, the "*C " marker and the name of the output stratum on the last line terminates the embedded SMAPs.

SMAP Syntax


SMAP:
Header { Section } EndSection

Header :
ID OutputFileName DefaultStratumId

ID:
SMAP CR

OutputFileName:
NONASTERISKSTRING CR

DefaultStratumId:
NONASTERISKSTRING CR

Section:
StratumSection
FileSection
LineSection
EmbeddedSourceMaps
VendorSection
FutureSection

EmbeddedSourceMaps :
OpenEmbeddedSection { SMAP } CloseEmbeddedSection

OpenEmbeddedSection :
*O StratumID CR

CloseEmbeddedSection :
*C StratumID CR

StratumSection :
*S StratumID CR

StratumID :
NONASTERISKSTRING

LineSection :
*L CR { LineInfo }

LineInfo :
InputLineInfo
: OutputLineInfo CR

InputLineInfo :
InputStartLine
, RepeatCount
InputStartLine

OutputLineInfo :
OutputStartLine
, OutputLineIncrement
OutputStartLine

InputStartLine :
NUMBER
NUMBER
# LineFileID

LineFileID :
FileID

RepeatCount :
NUMBER

OutputStartLine :
NUMBER

OutputLineIncrement :
NUMBER

FileSection :
*F CR { FileInfo }

FileInfo :
FileID FileName CR
+ FileID FileName CR AbsoluteFileName CR

FileID :
NUMBER

FileName:
NONASTERISKSTRING

AbsoluteFileName:
NONASTERISKSTRING

VendorSection:
*V CR VENDORID CR { VendorInfo }

VendorInfo:
NONASTERISKSTRING CR

FutureSection:
* OTHERCHAR CR { FutureInfo }

FutureInfo:
NONASTERISKSTRING CR

EndSection:
*E CR

Where {x} denotes zero or more occurrences of x . And where the terminals are defined as follows (whitespace is a sequence of zero or more spaces or tabs):

Terminals
NONASTERISKSTRING Any sequence of characters (excluding the terminal carriage-return or new-line) which does not start with "*". Leading whitespace is ignored.
NUMBER Non negative decimal integer. The number is terminated by the first non-digit character. Leading and trailing whitespace is ignored.
CR a line terminator: carriage-return, carriage-return followed by new-line or new-line.
OTHERCHAR Any character (other than carriage-return, new-line, space or tab) not already used as a section header (not S,F,L,V,O,C or E).
VENDORID A sequence of characters that identifies a vendor. The name is formed by the same rules that unique package names are formed in the Java language specification. Leading and trailing whitespace is ignored. The terminal carriage-return or new-line is excluded.


SMAP Resolution

Before the SMAP in a SMAP-file can be installed into the SourceDebugExtension attribute it must be resolved into an SMAP with no embedded SMAPs and with final-source as the output source. A set of embedded SMAPs is specific to a stratum and is resolved in the context of the matching StratumSection in the outer SMAP. The resolved SMAP includes StratumSections computed from each set of embedded SMAPs as well as the unchanged StratumSections of the outer SMAP. If embedded SMAPs are nested, the inner-most is resolved first.

The structure of an SMAP with embedded SMAPs is as follows:

SMAP
  ...
*O B
SMAP
  ...
*S A
  ...
*E
*C B
  ...
*S B
  ...
*E

The structure is a set of embedded SMAPs (for a stratum, here named B ), an outer StratumSection (for B ), and an embedded SMAP with a StratumSection (for a stratum, here named A ). Note that: there may be many sets of embedded SMAPs, many embedded SMAPs within the set of embedded SMAPs, and many StratumSections within an SMAP. A StratumSection maps source information from its stratum to an output stratum. Thus, the embedded StratumSection maps stratum A to stratum B . We know it is mapped to stratum B because the set of embedded SMAPs for stratum B corresponds to the input for the language-processor for B . The outer StratumSection maps stratum B to its output stratum (let's call this stratum C ), if the shown SMAP is the outer-most SMAP then stratum C is the final-source stratum. The purpose of resolution is to create a non-embedded StratumSection for A which maps to C (all StratumSections within an SMAP must map to the same output stratum, in a resolved outer-most SMAP all StratumSections will map to the final-source stratum). This is done by composing the mapping in the embedded StratumSection (from A to B ) with the mapping in the outer StratumSection (from B to C ). Since there may be many embedded StratumSections for A , these sections must be merged.

A StratumSection is computed for each stratum present in the embedded SMAPs. The computed StratumSection is the merge of each embedded StratumSection, for that stratum. Line number information is composed with the line number information of the outer StratumSection (note that the embedded StratumSections cannot be for the same stratum as the outer StratumSection). Specifically, a computed StratumSection consists of a merged FileSection , a composed LineSection , and direct copies of any VendorSection s or unknown sections. The merged FileSection includes each unique FileInfo , with FileIDs reassigned to be unique. The composition the LineSections is described in the algorithm below.

LineInfo Composition Algorithm

The following pseudo-code sketches the algorithm for resolving LineInfo in embedded SMAPs. LineInfo resolution is by composition - discussed above. An embedded LineInfo which maps stratum A to stratum B is composed with an outer LineInfo which maps stratum B to stratum C to create a new resolved LineInfo which maps stratum A to stratum C .

The SMAPs and their components are marked by subscript:

  • Embedded SMAP - levelE
  • Outer StratumSection - levelO
  • Resolved computed StratumSection - levelR

The inputs and outputs of the algorithm are LineInfo tuples. Line information is represented in this algorithm in its LineInfo format which is discussed in the LineSection This algorithm is invoked for each LineInfoE in each embedded SMAP.

ResolveLineInfo:
InputStartLineE #LineFileIDE , RepeatCountE : OutputStartLineE , OutputLineIncrementE
as follows {
if RepeatCountE > 0 then {
for each LineInfoO in the stratum of the embedded SMAP :
InputStartLineO #LineFileIDO , RepeatCountO : OutputStartLineO , OutputLineIncrementO
which includes OutputStartLineE
that is, InputStartLineO + N == OutputStartLineE
for some offset into the outer input range N where 0 <= N < RepeatCountO
and for which LineFileIDO has a sourceName matching the embedded SMAP's OutputFileName {
compute the number of outer mapping repeations which can be applied
available := RepeatCountO - N ;
compute the number of embedded mapping repeations which can be applied
completeCount :=
floor (available / OutputLineIncrementE ) min RepeatCountE ;
if completeCount > 0 then {
output resolved LineInfo
InputStartLineE #
uniquify (LineFileIDE ), completeCount :
(OutputStartLineO + (N * OutputLineIncrementO )),
(OutputLineIncrementE * OutputLineIncrementO ) ;
ResolveLineInfo
(InputStartLineE + completeCount ) #LineFileIDE , (RepeatCountE - completeCount ) :
(OutputStartLineE + completeCount * OutputLineIncrementE ), OutputLineIncrementE ;
}
else {
output resolved LineInfo
InputStartLineE #
uniquify (LineFileIDE ), 1 :
(OutputStartLineO + (N * OutputLineIncrementO )), available ;
ResolveLineInfo
InputStartLineE #LineFileIDE , 1 :
(OutputStartLineE + available ), (OutputLineIncrementE - available ) ;
ResolveLineInfo
(InputStartLineE + 1) #LineFileIDE , (RepeatCountE - 1):
(OutputStartLineE + OutputLineIncrementE ), OutputLineIncrementE ;
}
}
}
}

where uniquify converts a LineFileIDE to a corresponding LineFileIDR

Resolution Example

The following example demonstrates resolution with this algorithm. The general example will provide context before walking through this example. In this example, Incl.bar is included by Hi.bar , but each is the result of a prior translation.

 

                                                                                                   
         |  Hi.foo                         |  Incl.foo     
         |                              |          
language-processorFoo
           
language-processorFoo
    |          |                    |          |     
    |  Hi.bar     |  Hi.bar.smap               |  Incl.bar     |  Incl.bar.smap
    |          |                    |          |     
language-processorBar
                   |          |                    
                   |  Hi.java     |  Hi.java.smap                    
                   |          |                    
               
javac compiler
     |                    
                   |          |                    
                   |  Hi.class|                         
                   |          |                    
               
post-processor
               
                        |                         
                        |  Hi.class               

If the unresolved SMAP (in Hi.java.smap ) is as follows

SMAP
Hi.java
Java
  Outer Header
*O Bar   OpenEmbeddedSection
SMAP
Hi.bar
Java
*S Foo
*F
1 Hi.foo
*L
1#1,5:1,2
*E
  Embedded SMAP (Hi.bar)
SMAP
Incl.bar
Java
*S Foo
*F
1 Incl.foo
*L
1#1,2:1,2
*E
  Embedded SMAP (Incl.bar)
*C Bar   CloseEmbeddedSection
*S Bar
*F
1 Hi.bar
2 Incl.bar
*L
1#1:1
1#2,4:2
3#1,8:6
  Outer StratumSection
*E   Final EndSection

The merged levelR FileSection is (in stratum Foo ):

*F
1 Hi.foo
2 Incl.foo

The computation proceeds as follows --

LineInfoE LineInfoE
recursion 1
LineInfoE
recursion 2
matching
outer
LineInfoO
resolved
LineInfoR
discussion
1#1,5:1,2    1#1:1 1#1,1:1,1 ResolveLineInfo is called for 1#1,5:1,2 (from the first embedded SMAP - OutputFileName is Hi.bar ). 1#1:1 is found as the outer StratumSection LineInfoO with InputStartLineO of 1 and LineFileIDO has a sourceName matching Hi.bar . N is 0, and completeCount is 0, thus the else branch is taken. available is 1 and thus output is 1#1,1:1,1 .
  1#1,1:2,1   no match   The remaining half of the initial LineInfoE mapping then must be resolved recursively, but there is no match and it is ignored.
  2#1,4:3,2   3#1,8:6 2#1,4:6,2 The remaining mappings are also handled recursively. There is a matching LineInfoO . N is 0, and completeCount is 4, thus the if branch is taken.
   6#1,0:11,2 n/a  The recursive resolve descends deeper but does nothing since all of RepeatCountE has been mapped. The first LineInfoE is now resolved. Since it had only one LineInfoE the first SMAP is also resolved.
1#1,2:1,2    1#2,4:2 1#2,2:2,2 Now for the second SMAP (OutputFileName is Incl.bar ). FileIDE 1 in this SMAP is Incl.foo which corresponds to the remapped FileIDR 2. So the matching LineInfoO is 1#2,4:2 . N is 0, and completeCount is 2, so the if branch is taken.
  3#1,0:5,2  n/a  The recursive resolve does nothing since all the maps have been handled. Resolution is complete.

The resultant resolved SMAP is:

SMAP
Hi.java
Java
*S Foo
*F
1 Hi.foo
2 Incl.foo
*L
1#1,1:1,1
2#1,4:6,2
1#2,2:2,2
*S Bar
*F
1 Hi.bar
2 Incl.bar
*L
1#1:1
1#2,4:2
3#1,8:6
*E


JPDA Support

The Java Platform Debugger Architecture in the Merlin release has been extended in support of debugging other languages. The new APIs and APIs with comments changed to include reference to strata are listed below:

New APIsAPIs with Changed Comments
JVMDI
GetSourceDebugExtension  
JDWP - ReferenceType (2) Command Set
SourceDebugExtension Command (12) 
JDWP - VirtualMachine (1) Command Set
SetDefaultStratum Command (19) 
JDI - VirtualMachine interface
void setDefaultStratum(String stratum)  
String getDefaultStratum()  
JDI - ReferenceType interface
String sourceNames(String stratum) String sourceName()
String sourcePaths(String stratum)  
List allLineLocations(String stratum, String sourceName) List allLineLocations()
List locationsOfLine(String stratum, String sourceName, int lineNumber) List locationsOfLine(int lineNumber)
List availableStrata()  
String defaultStratum()  
String sourceDebugExtension()  
JDI - Method interface
List allLineLocations(String stratum, String sourceName) List allLineLocations()
List locationsOfLine(String stratum, String sourceName, int lineNumber) List locationsOfLine(int lineNumber)
JDI - Location interface
  class comment (strata defined)
int lineNumber(String stratum) int lineNumber()
String sourceName(String stratum) String sourceName()
String sourcePath(String stratum)  
String sourcePath()  


SourceDebugExtension Support

Debugger applications frequently need debugging information about the source that exceeds what is delivered by the existing JavaTM Virtual Machine class file attributes (SourceFile, LineNumber, and LocalVariable). This is particularly true for debugging the source of other languages. In a distributed environment side files may not be accessible, the information must be directly associated with the class.

The solution is the addition of a class file attribute which holds a string; The string contains debugging information in a standardized format which allows for evolution and vendor extension.

SourceDebugExtension Access

This string is made opaquely accessible at the three layers of the Java Platform Debugger Architecture (JPDA):

JVMDIGetSourceDebugExtension(jclass clazz, char **sourceDebugExtensionPtr)
JDWPSourceDebugExtension Command (12) in the ReferenceType (2) Command Set
JDIString sourceDebugExtension() in the ReferenceType interface

SourceDebugExtension Class File Attribute

Java virtual machine class file attributes are described in section 4.7 of the The Java Virtual Machine Specification . The definition of the added attribute is in the context of The Java Virtual Machine Specification:

The SourceDebugExtension attribute is an optional attribute in the attributes table of the ClassFile structure. There can be no more than one SourceDebugExtension attribute in the attributes table of a given ClassFile structure.

The SourceDebugExtension attribute has the following format:

 


    SourceDebugExtension_attribute {
     u2 attribute_name_index;
     u4 attribute_length;
     u1 debug_extension[attribute_length];
    }

The items of the SourceDebugExtension_attribute structure are as follows:

 

attribute_name_index
The value of the attribute_name_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure representing the string "SourceDebugExtension" .

 

attribute_length
The value of the attribute_length item indicates the length of the attribute, excluding the initial six bytes. The value of the attribute_length item is thus the number of bytes in the debug_extension[] item.

 

debug_extension[]
The debug_extension array holds a string, which must be in UTF-8 format. There is no terminating zero byte.

The string in the debug_extension item will be interpreted as extended debugging information. The content of this string has no semantic effect on the Java Virtual Machine.

 


Example

The example below shows how the process described above would apply to a tiny JSP program.

Input Source

The input consists of two JSP files, the first is Hello.jsp :

  1   <HTML>
  2   <HEAD>
  3   <TITLE>Hello Example</TITLE>
  4   </HEAD>
  5   <BODY>
  6   <%@ include file="greeting.jsp" %>
  7   </BODY>
  8   </HTML>

The second JSP file is the included file greeting.jsp :

  1   Hello There!<P>
  2   Goodbye on <%= new Date() %>

Language Processor

When a JSP compiler (the language-processor ) compiles these files it will produce two outputs - a Java programming language source file and a SMAP-file . The generated Java programming language source file is HelloServlet.java :

  1   import javax.servlet.*;
  2   import javax.servlet.http.*;
  3   
  4   public class HelloServlet extends HttpServlet {
  5     public void doGet(HttpServletRequest request,
  6         HttpServletResponse response)
  7         throws ServletException, IOException {
  8       response.setContentType("text/html");
  9       PrintWriter out = response.getWriter();
  10   // Hello.jsp:1
  11       out.println("<HTML>");
  12   // Hello.jsp:2
  13       out.println("<HEAD>");
  14   // Hello.jsp:3
  15       out.println("<TITLE>Hello Example</TITLE>");
  16   // Hello.jsp:4
  17       out.println("</HEAD>");
  18   // Hello.jsp:5
  19       out.println("<BODY>");
  20   // greeting.jsp:1
  21       out.println("Hello There!<P>");
  22   // greeting.jsp:2
  23       out.println("Goodbye on " + new Date() );
  24   // Hello.jsp:7
  25       out.println("</BODY>");
  26   // Hello.jsp:8
  27       out.println("</HTML>");
  28     }
  29   }

The generated SMAP-file is HelloServlet.java.smap :

SMAP
HelloServlet.java
JSP
*S JSP
*F
1 Hello.jsp
2 greeting.jsp
*L
1#1,5:10,2
1#2,2:20,2
7#1,2:24,2
*E

A couple things are interesting to note about this SMAP -- the user has chosen to make JSP the default stratum (perhaps by a command line option) and even though there are ten lines of input source and 29 lines of generated source, only three LineInfo lines describe the transformation: the first and last are for the lines before and after the include (respectively) and the middle is for the included file greeting.jsp .

The three LineInfo lines describe these mappings:

 

   1#1,5:10,2 
Hello.jsp: line 1 -> HelloServlet.java: lines 10, 11
line 2 -> lines 12, 13
line 3 -> lines 14, 15
line 4 -> lines 16, 17
line 5 -> lines 18, 19

1#2,2:20,2
greeting.jsp: line 1 -> HelloServlet.java: lines 20, 21
line 2 -> lines 22, 23

7#1,2:24,2
Hello.jsp: line 7 -> HelloServlet.java: lines 24, 25
line 8 -> lines 26, 27

Post Processor

Next HelloServlet.java is compiled by a Java programming language compiler (for example javac ) producing the class file HelloServlet.class . Then the post-processor is run. It takes HelloServlet.class and HelloServlet.java.smap as input. It creates a SourceDebugExtension attribute whose content is the SMAP in HelloServlet.java.smap and rewrites HelloServlet.class with this attribute.

Debugging

Now the program is run under the control of a debugger (which is a client of JDI ). Let's say we are stepping through this code and the debugger has just received a JDI StepEvent for the line that is just about to output <BODY> . The debugger's code might look like this (the StepEvent is in the variable stepEvent ):

Location location = stepEvent.location();
String sourceName = location.sourceName("Java");
int lineNumber = location.lineNumber("Java");
displaySource(sourceName, lineNumber);

where displaySource is a debugger routine that displays a source location. Because the Java stratum has been specified sourceName would be HelloServlet.java , the lineNumber would be 19 and the displayed line would be:

out.println("<BODY>");

However, if sourceName and lineNumber were derived as follows:

String sourceName = location.sourceName("JSP");
int lineNumber = location.lineNumber("JSP");

Since the JSP stratum has been specified, sourceName would be Hello.jsp , the lineNumber would be 5 and the displayed line would be:

<BODY>

This occurs because the SourceDebugExtension attribute was stored when the VM read HelloServlet.class and it was retrieved with the SourceDebugExtension JDWP command which in turn caused the JVMDI function call GetSourceDebugExtension. The SMAP in the SourceDebugExtension was parsed which provided the above transformation of source location. Specifically, the line:

1#1,5:10,2

is the basis of this transformation - which refers to FileId #1

1 Hello.jsp

and whence the sourceName information. Since the default stratum specified in the SMAP is JSP , the code:

String sourceName = location.sourceName();
int lineNumber = location.lineNumber();

would have the same effect. Since this is the form code would have taken before these extensions were introduced, existing debuggers can be utilized if they are run under the new implementation of JDI .

 


Debugging Support for Other Languages Specification ("Specification")
Version: 1.0
Status: FCS
Release: November 24, 2003

Copyright 2003 Sun Microsystems, Inc.

4150 Network Circle, Santa Clara, California 95054, U.S.A
All rights reserved.

NOTICE; LIMITED LICENSE GRANTS

Sun Microsystems, Inc. ("Sun") hereby grants you a fully-paid, non-exclusive, non-transferable, worldwide, limited license (without the right to sublicense), under the Sun's applicable intellectual property rights to view, download, use and reproduce the Specification only for the purpose of internal evaluation, which shall be understood to include developing applications intended to run on an implementation of the Specification provided that such applications do not themselves implement any portion(s) of the Specification.

Sun also grants you a perpetual, non-exclusive, worldwide, fully paid-up, royalty free, limited license (without the right to sublicense) under any applicable copyrights or patent rights it may have in the Specification to create and/or distribute an Independent Implementation of the Specification that: (i) fully implements the Spec(s) including all its required interfaces and functionality; (ii) does not modify, subset, superset or otherwise extend the Licensor Name Space, or include any public or protected packages, classes, Java interfaces, fields or methods within the Licensor Name Space other than those required/authorized by the Specification or Specifications being implemented; and (iii) passes the TCK (including satisfying the requirements of the applicable TCK Users Guide) for such Specification. The foregoing license is expressly conditioned on your not acting outside its scope. No license is granted hereunder for any other purpose.

You need not include limitations (i)-(iii) from the previous paragraph or any other particular "pass through" requirements in any license You grant concerning the use of your Independent Implementation or products derived from it. However, except with respect to implementations of the Specification (and products derived from them) that satisfy limitations (i)-(iii) from the previous paragraph, You may neither: (a) grant or otherwise pass through to your licensees any licenses under Sun's applicable intellectual property rights; nor (b) authorize your licensees to make any claims concerning their implementation's compliance with the Spec in question.

For the purposes of this Agreement: "Independent Implementation " shall mean an implementation of the Specification that neither derives from any of Sun's source code or binary code materials nor, except with an appropriate and separate license from Sun, includes any of Sun's source code or binary code materials; and "Licensor Name Space " shall mean the public class or interface declarations whose names begin with "java", "javax", "com.sun" or their equivalents in any subsequent naming convention adopted by Sun through the Java Community Process, or any recognized successors or replacements thereof.

This Agreement will terminate immediately without notice from Sun if you fail to comply with any material provision of or act outside the scope of the licenses granted above.

TRADEMARKS

No right, title, or interest in or to any trademarks, service marks, or trade names of Sun or Sun's licensors is granted hereunder.  Sun, Sun Microsystems, the Sun logo, Java, and the Java Coffee Cup logo are trademarks or registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries.

DISCLAIMER OF WARRANTIES

THE SPECIFICATION IS PROVIDED "AS IS".  SUN MAKES NO REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, THAT THE CONTENTS OF THE SPECIFICATION ARE SUITABLE FOR ANY PURPOSE OR THAT ANY PRACTICE OR IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADE SECRETS OR OTHER RIGHTS.  This document does not represent any commitment to release or implement any portion of the Specification in any product.

THE SPECIFICATION COULD INCLUDE TECHNICAL INACCURACIES OR TYPOGRAPHICAL ERRORS.  CHANGES ARE PERIODICALLY ADDED TO THE INFORMATION THEREIN; THESE CHANGES WILL BE INCORPORATED INTO NEW VERSIONS OF THE SPECIFICATION, IF ANY.  SUN MAY MAKE IMPROVEMENTS AND/OR CHANGES TO THE PRODUCT(S) AND/OR THE PROGRAM(S) DESCRIBED IN THE SPECIFICATION AT ANY TIME.  Any use of such changes in the Specification will be governed by the then-current license for the applicable version of the Specification.

LIMITATION OF LIABILITY

TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES, INCLUDING WITHOUT LIMITATION, LOST REVENUE, PROFITS OR DATA, OR FOR SPECIAL, INDIRECT, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF OR RELATED TO ANY FURNISHING, PRACTICING, MODIFYING OR ANY USE OF THE SPECIFICATION, EVEN IF SUN AND/OR ITS LICENSORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

You will indemnify, hold harmless, and defend Sun and its licensors from any claims arising or resulting from: (i) your use of the Specification; (ii) the use or distribution of your Java application, applet and/or clean room implementation; and/or (iii) any claims that later versions or releases of any Specification furnished to you are incompatible with the Specification provided to you under this license.

RESTRICTED RIGHTS LEGEND

U.S. Government: If this Specification is being acquired by or on behalf of the U.S. Government or by a U.S. Government prime contractor or subcontractor (at any tier), then the Government's rights in the Specification and accompanying documentation shall be only as set forth in this license; this is in accordance with 48 C.F.R. 227.7201 through 227.7202-4 (for Department of Defense (DoD) acquisitions) and with 48 C.F.R. 2.101 and 12.212 (for non-DoD acquisitions).

REPORT

You may wish to report any ambiguities, inconsistencies or inaccuracies you may find in connection with your use of the Specification ("Feedback"). To the extent that you provide Sun with any Feedback, you hereby: (i) agree that such Feedback is provided on a non-proprietary and non-confidential basis, and (ii) grant Sun a perpetual, non-exclusive, worldwide, fully paid-up, irrevocable license, with the right to sublicense through multiple levels of sublicensees, to incorporate, disclose, and use without limitation the Feedback for any purpose related to the Specification and future versions, implementations, and test suites thereof.

(LFI#136249/Form ID#011801)


Last modified: Fri Oct 3 14:48:10 PDT 2003


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值