рд╣рдо рдЕрдзрд┐рдХрддрдо рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ: рдУрдЖрд░рдПрдо рд╕реЗ рдмрд╛рдЗрдЯрдХреЛрдб рд╡рд┐рд╢реНрд▓реЗрд╖рдг рддрдХ

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ, рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреЛ рдЕрдкрдиреЗ рдЬреАрд╡рди рдореЗрдВ 3 рдЪреАрдЬреЗрдВ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдП: рдЕрдкрдиреА рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдмрдирд╛рдПрдВ, рдЕрдкрдирд╛ рдЦреБрдж рдХрд╛ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рд▓рд┐рдЦреЗрдВ рдФрд░ рдЕрдкрдирд╛ рдУрдЖрд░рдПрдо рдмрдирд╛рдПрдВред рдФрд░ рдЕрдЧрд░ рдореИрдВрдиреЗ рдПрдХ рд▓рдВрдмреЗ рд╕рдордп рдкрд╣рд▓реЗ рднрд╛рд╖рд╛ рд▓рд┐рдЦреА рдереА (рд╢рд╛рдпрдж рдореИрдВ рдЖрдкрдХреЛ рдХреБрдЫ рдФрд░ рд╕рдордп рдмрддрд╛рдКрдВрдЧрд╛), рдФрд░ рдУрдПрд╕ рдЕрднреА рднреА рдЖрдЧреЗ рд╣реИ, рддреЛ рдореИрдВ рдЖрдкрдХреЛ рдУрдЖрд░рдПрдо рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрднреА рдмрддрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдЕрдзрд┐рдХ рд╕рдЯреАрдХ рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП, рдпрд╣ рдУрдЖрд░рдПрдо рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рднреА рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ рдЫреЛрдЯреЗ, рд╕реНрдерд╛рдиреАрдп рдФрд░, рдЬреИрд╕рд╛ рдХрд┐ рд▓рдЧ рд░рд╣рд╛ рдерд╛, рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рд░рд▓ рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВред


рдПрдХ рд╕рд╛рде рд╣рдо рдЕрдкрдиреА рдирд╛рдЬреБрдХрддрд╛ рдФрд░ рдЧрд▓рддрддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдЧрд░реВрдХрддрд╛ рдХреА рдХрдбрд╝рд╡рд╛рд╣рдЯ рдХрд╛ рдПрдХ рд╕рд░рд▓ рд╕рдорд╛рдзрд╛рди рдЦреЛрдЬрдиреЗ рдХреА рдЦреБрд╢реА рд╕реЗ рд╕рднреА рддрд░рд╣ рд╕реЗ рдЬрд╛рдПрдВрдЧреЗред рдПрдХ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдПрдкреАрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рд▓реЗрдХрд░ рдЧрдВрджреЗ рд╣реИрдХ рддрдХред "рд▓рдЧрднрдЧ рдмрд┐рдирд╛ рдкреНрд░рддрд┐рдмрд┐рдВрдм" рд╕реЗ "рдмрд╛рдЗрдЯ-рдХреЛрдб рджреБрднрд╛рд╖рд┐рдпрд╛ рдореЗрдВ рдШреБрдЯрдиреЗ рддрдХ рдЧрд╣рд░рд╛ред"


рдХреМрди рдкрд░рд╡рд╛рд╣ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдмрд╛рдЗрдЯрдХреЛрдб рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдпрд╣ рдХрд┐рди рдХрдард┐рдирд╛рдЗрдпреЛрдВ рд╕реЗ рднрд░рд╛ рд╣реЛрддрд╛ рд╣реИ, рдФрд░ рдЕрдВрдд рдореЗрдВ рдЖрдкрдХреЛ рдХреНрдпрд╛ рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ рдкрд░рд┐рдгрд╛рдо рдорд┐рд▓ рд╕рдХрддрд╛ рд╣реИ, рдмрд┐рд▓реНрд▓реА рдХрд╛ рд╕реНрд╡рд╛рдЧрдд рд╣реИред


рд╕рд╛рдордЧреНрд░реА


1 - рдпрд╣ рд╕рдм рдХреИрд╕реЗ рд╢реБрд░реВ рд╣реБрдЖред
2-4 - рдмрд╛рдпрдЯреЗрдХреЛрдб рдХреЗ рд░рд╛рд╕реНрддреЗ рдореЗрдВред
5 - рдмрд╛рдИрдЯрдХреЛрдб рдХреМрди рд╣реИред
6 - рд╡рд┐рд╢реНрд▓реЗрд╖рдг рд╣реАред рдпрд╣ рдЗрд╕ рдЕрдзреНрдпрд╛рдп рдХреЗ рд▓рд┐рдП рдерд╛ рдХрд┐ рд╕рдм рдХреБрдЫ рдХрд▓реНрдкрдирд╛ рдХреА рдЧрдИ рдереА рдФрд░ рдпрд╣ рдмрд╣реБрдд рд╣рд┐рдореНрдордд рдореЗрдВ рдерд╛ред
7 - рдФрд░ рдХреНрдпрд╛ рдЦрддреНрдо рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рд╕рдкрдиреЗ, рд╕рдкрдиреЗ ...
рдЖрдлреНрдЯрд░рд╡рд░реНрдб - рдЖрдлреНрдЯрд░рд╡рд░реНрдбред


UPD: рдкреНрд░рдХрд╛рд╢рди рдХреЗ рддреБрд░рдВрдд рдмрд╛рдж, 6-8 рднрд╛рдЧ рдЦреЛ рдЧрдП (рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рд╕рдм рдХреБрдЫ рд╢реБрд░реВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛)ред рдлрд┐рдХреНрд╕реНрдбред



рднрд╛рдЧ рдПрдХ рд╕рдорд╕реНрдпрд╛


рдХрд▓реНрдкрдирд╛ рдХреАрдЬрд┐рдП рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд╕рд░рд▓ рдпреЛрдЬрдирд╛ рд╣реИред рдПрдХ рдЧреНрд░рд╛рд╣рдХ рд╣реИ, рдЙрд╕рдХреЗ рдХрдИ рдЦрд╛рддреЗ рд╣реИрдВред рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдПрдХ рдЧреНрд░рд╛рд╣рдХ рдХреЗ рдкрд╛рд╕ рдХрдИ рд╕рд┐рдо рдХрд╛рд░реНрдб рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рд╕рд┐рдо рдХрд╛рд░реНрдб рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдпрд╛ рдПрдХ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдЧреНрд░рд╛рд╣рдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред



рдпрд╣рд╛рдВ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдореЙрдбрд▓ рд╣рдорд╛рд░реЗ рдХреЛрдб (рдЧреЗрдЯрд┐рдВрдЧ рдЧреЗрдЯрд░реНрд╕ / рд╕реЗрдЯрд░ / рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ / ...) рдореЗрдВ рдХреИрд╕реЗ рд╡рд░реНрдгрд┐рдд рд╣реИред


@JdbcEntity(table = "CLIENT") public class Client { @JdbcId private Long id; @JdbcColumn private String name; @JdbcJoinedObject(localColumn = "DEFAULTACCOUNT") private Account defaultAccount; } @JdbcEntity(table = "ACCOUNT") public class Account { @JdbcId private Long id; @JdbcColumn private Long balance; @JdbcJoinedObject(localColumn = "CLIENT") private Client client; } @JdbcEntity(table = "CARD") public class Card { @JdbcId private Long id; @JdbcColumn private String msisdn; @JdbcJoinedObject(localColumn = "ACCOUNT") private Account account; @JdbcJoinedObject(localColumn = "CLIENT") private Client client; } 

рдУрдЖрд░рдПрдо рдореЗрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгрд┐рдпреЛрдВ рдХреА рдЕрдиреБрдкрд╕реНрдерд┐рддрд┐ рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (рд╣рдореЗрдВ рдЗрд╕ рд╡рд┐рд╢реЗрд╖ рд╡рд░реНрдЧ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рдирд╛ рд╣реЛрдЧрд╛) рдФрд░ рдПрдХ рдЕрдиреБрд░реЛрдзред рддрджрдиреБрд╕рд╛рд░, рдпрд╣рд╛рдВ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдирдХреНрд╢рд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╕рдордп рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЛ рдХреНрдпрд╛ рднреЗрдЬрд╛ рдЬрд╛рддрд╛ рд╣реИред


 select CARD.id id, CARD.msisdn msisdn, ACCOUNT_2.id ACCOUNT_2_id, ACCOUNT_2.balance ACCOUNT_2_balance, CLIENT_3.id CLIENT_3_id, CLIENT_3.name CLIENT_3_name, CLIENT_1.id CLIENT_1_id, CLIENT_1.name CLIENT_1_name, ACCOUNT_4.id ACCOUNT_4_id, ACCOUNT_4.balance ACCOUNT_4_balance from CARD left outer join CLIENT CLIENT_1 on CARD.CLIENT = CLIENT_1.id left outer join ACCOUNT ACCOUNT_2 on CARD.ACCOUNT = ACCOUNT_2.id left outer join CLIENT CLIENT_3 on ACCOUNT_2.CLIENT = CLIENT_3.id left outer join ACCOUNT ACCOUNT_4 on CLIENT_1.DEFAULTACCOUNT = ACCOUNT_4.id; 

Uupsред рдЧреНрд░рд╛рд╣рдХ рдФрд░ рдмрд┐рд▓ рдХреА рдирдХрд▓ рдХреА рдЬрд╛рддреА рд╣реИред рд╕рдЪ рд╣реИ, рдЕрдЧрд░ рдЖрдк рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИ - рдЖрдЦрд┐рд░рдХрд╛рд░, рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЛ рдкрддрд╛ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдХрд╛рд░реНрдб рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рдХрд╛рд░реНрдб рдЕрдХрд╛рдЙрдВрдЯ рдХреНрд▓рд╛рдЗрдВрдЯ рдПрдХ рд╣реА рдХреНрд▓рд╛рдЗрдВрдЯ рд╣реИрдВред рдПрдХ рдХреНрд╡реЗрд░реА рдХреЛ рд╕рд╛рдВрдЦреНрдпрд┐рдХреАрдп рд░реВрдк рд╕реЗ рдФрд░ рдХреЗрд╡рд▓ рдПрдХ рд╣реА рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (рдЕрдиреБрд░реЛрдз рдХреА рд╡рд┐рд╢рд┐рд╖реНрдЯрддрд╛ рдкрд░ рдкреНрд░рддрд┐рдмрдВрдз рдпрд╛рдж рд░рдЦреЗрдВ?)ред


рд╡реИрд╕реЗ, рдмрд┐рд▓реНрдХреБрд▓ рдЙрд╕реА рдХрд╛рд░рдг рд╕реЗ, рдпрд╣рд╛рдБ рдкрд░ рдХреЛрдИ Card.account.client.defaultAccount рдФрд░ Card.client.defaultAccount.client рдлрд╝реАрд▓реНрдб рдирд╣реАрдВ рд╣реИрдВред рдХреЗрд╡рд▓ рд╣рдо рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ client рдФрд░ client.defaultAccount.client рд╣рдореЗрд╢рд╛ рдореЗрд▓ рдЦрд╛рддреЗ рд╣реИрдВред рдФрд░ рдврд╛рдВрдЪрд╛ рдирд╣реАрдВ рдЬрд╛рдирддрд╛, рдЙрд╕рдХреЗ рд▓рд┐рдП рдпрд╣ рдПрдХ рдордирдорд╛рдирд╛ рд▓рд┐рдВрдХ рд╣реИред рдФрд░ рдРрд╕реЗ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдХреНрдпрд╛ рдХрд░рдирд╛ рдмрд╣реБрдд рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИред рдореБрдЭреЗ рдкрддрд╛ рд╣реИ 3 рд╡рд┐рдХрд▓реНрдк:


  1. рд╡реНрдпрд╛рдЦреНрдпрд╛рдУрдВ рдореЗрдВ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдЖрдХреНрд░рдордгрдХрд╛рд░рд┐рдпреЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░реЗрдВред
  2. рдкреБрдирд░рд╛рд╡рд░реНрддреА рдкреНрд░рд╢реНрди ( with recursive / connect by with recursive ) рдмрдирд╛рдПрдВред
  3. рд╕реНрдХреЛрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред

рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╣рдордиреЗ рдХреМрди рд╕рд╛ рд╡рд┐рдХрд▓реНрдк рдЪреБрдирд╛? рдпрд╣ рд╕рд╣реА рд╣реИред рдирддреАрдЬрддрди, рд╕рднреА рдкреБрдирд░рд╛рд╡рд░реНрддреА рдХреНрд╖реЗрддреНрд░ рдЕрдм рдмрд┐рд▓реНрдХреБрд▓ рднреА рдирд╣реАрдВ рднрд░реЗ рд╣реИрдВ рдФрд░ рд╣рдореЗрд╢рд╛ рд╢реВрдиреНрдп рд╣реИред


рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдЖрдк рдмрд╛рд░реАрдХреА рд╕реЗ рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рджреЛрд╣рд░рд╛рд╡ рдХреЗ рдкреАрдЫреЗ рджреВрд╕рд░реА рд╕рдорд╕реНрдпрд╛ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдпрд╣ рдмрд╣реБрдд рдмреБрд░рд╛ рд╣реИред рд╣рдо рдХреНрдпрд╛ рдЪрд╛рд╣рддреЗ рдереЗ? рдХрд╛рд░реНрдб рдирдВрдмрд░ рдФрд░ рд╕рдВрддреБрд▓рдиред рдЖрдкрдХреЛ рдХреНрдпрд╛ рдорд┐рд▓рд╛? 4 рдЬреЛрдбрд╝ рдФрд░ 10 рдХреЙрд▓рдоред рдФрд░ рдпрд╣ рдмрд╛рдд рддреЗрдЬреА рд╕реЗ рдмрдврд╝ рд░рд╣реА рд╣реИ! рдЦреИрд░ рдпрд╛рдиреА рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рдРрд╕реА рд╕реНрдерд┐рддрд┐ рд╣реИ рдЬрд╣рд╛рдВ, рдкрд╣рд▓реЗ, рд╕реБрдВрджрд░рддрд╛ рдФрд░ рдЕрдЦрдВрдбрддрд╛ рдХреЗ рд▓рд┐рдП, рд╣рдо рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдПрдиреЛрдЯреЗрд╢рди рдкрд░ рдореЙрдбрд▓ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░, 5 рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд▓рд┐рдП , 15 рдЬреЛрдбрд╝ рдФрд░ 150 рдХреЙрд▓рдо рдХреЗ рд▓рд┐рдП рдЕрдиреБрд░реЛрдз рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдФрд░ рдЗрд╕ рд╕рдордп рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдбрд░рд╛рд╡рдирд╛ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред



рднрд╛рдЧ рджреЛ рдПрдХ рдХрд╛рдо рд▓реЗрдХрд┐рди рдЕрд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╕рдорд╛рдзрд╛рди


рдПрдХ рд╕рд░рд▓ рд╕рдорд╛рдзрд╛рди рддреБрд░рдВрдд рднреАрдЦ рдорд╛рдБрдЧрддрд╛ рд╣реИред рдХреЗрд╡рд▓ рдЙрди рд╕реНрдкреАрдХрд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдЬрд┐рдиреНрд╣реЗрдВ рдЦреАрдВрдЪрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП! рдХрд╣рдирд╛ рдЖрд╕рд╛рди рд╣реИред рд╕рдмрд╕реЗ рд╕реНрдкрд╖реНрдЯ рд╡рд┐рдХрд▓реНрдк (рдЕрдкрдиреЗ рд╣рд╛рдереЛрдВ рд╕реЗ рдЪрдпрди рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП) рд╣рдо рддреБрд░рдВрдд рдЫреЛрдбрд╝ рджреЗрдВрдЧреЗред рдЦреИрд░, рддрдм рдирд╣реАрдВ, рд╣рдордиреЗ рдореЙрдбрд▓ рдХрд╛ рд╡рд░реНрдгрди рдХрд┐рдпрд╛ рддрд╛рдХрд┐ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рди рдХрд┐рдпрд╛ рдЬрд╛рдПред рдХрд╛рдлреА рд╕рдордп рдкрд╣рд▓реЗ рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╡рд┐рдзрд┐ рдмрдирд╛рдИ рдЧрдИ рдереА - partialGet ред рдпрд╣, рд╕рд░рд▓ get рд╡рд┐рдкрд░реАрдд, List<String> - рднрд░реЗ рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рдирд╛рдо рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдкрд╣рд▓реЗ рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдореЗрдВ рдЙрдкрдирд╛рдо рджрд░реНрдЬ рдХрд░рдирд╛ рд╣реЛрдЧрд╛


 @JdbcJoinedObject(localColumn = "ACCOUNT", sqlTableAlias = "a") private Account account; @JdbcJoinedObject(localColumn = "CLIENT", sqlTableAlias = "c") private Client client; 

рдФрд░ рдлрд┐рд░ рдкрд░рд┐рдгрд╛рдо рдХрд╛ рдЖрдирдВрдж рд▓реЗрдВред


 List<String> requiredColumns = asList("msisdn", "c_a_balance", "a_balance"); String query = cardMapper.getSelectSQL(requiredColumns, DatabaseType.ORACLE); System.out.println(query); 

 select CARD.msisdn msisdn, c_a.balance c_a_balance, a.balance a_balance from CARD left outer join ACCOUNT a on CARD.ACCOUNT = a.id left outer join CLIENT c on CARD.CLIENT = c.id left outer join ACCOUNT c_a on c.DEFAULTACCOUNT = c_a.id; 

рдФрд░ рд╕рдм рдХреБрдЫ рдареАрдХ рд▓рдЧрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдирд╣реАрдВред рдпрд╣рд╛рдВ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдХреЛрдб рдореЗрдВ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред


 Card card = cardDAO.partialGet(cardId, "msisdn", "c_a_balance", "a_balance"); ... ... ...    ... ... ... long clientId = card.getClient().getId();//, NPE.  , id    ?! 

рдФрд░ рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рдЖрдк рдЕрдм рдХреЗрд╡рд▓ рдкрд╛рд░реНрдЯрдЧреЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрджрд┐ рдЗрд╕рдХреЗ рдмреАрдЪ рдХреА рджреВрд░реА рдФрд░ рдкрд░рд┐рдгрд╛рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреЗрд╡рд▓ рдХреБрдЫ рдкрдВрдХреНрддрд┐рдпрд╛рдБ рд╣реИрдВред рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдкрд░рд┐рдгрд╛рдо рджреВрд░ рдЬрд╛рддрд╛ рд╣реИ рдпрд╛, рднрдЧрд╡рд╛рди рди рдХрд░реЗ, рдХрд┐рд╕реА рд╡рд┐рдзрд┐ рдХреЗ рдЕрдВрджрд░ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рд╕рдордЭрдирд╛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрд╣реБрдд рдореБрд╢реНрдХрд┐рд▓ рд╣реИ рдХрд┐ рдХреМрди рд╕реЗ рдХреНрд╖реЗрддреНрд░ рднрд░реЗ рд╣реБрдП рд╣реИрдВ рдФрд░ рдХреМрди рд╕реЗ рдирд╣реАрдВ рд╣реИрдВред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЕрдЧрд░ рдПрдирдкреАрдИ рдХрд╣реАрдВ рд╣реБрдЖ, рддреЛ рдЖрдкрдХреЛ рдЕрднреА рднреА рдпрд╣ рд╕рдордЭрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрд╢рдХреНрдд рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рд╡рд╛рдкрд╕ рдЖ рдЧрдпрд╛ рд╣реИ, рдпрд╛ рдХреНрдпрд╛ рд╣рдордиреЗ рдЕрднреА рдЗрд╕ рдХреНрд╖реЗрддреНрд░ рдХреЛ рдирд╣реАрдВ рднрд░рд╛ рд╣реИред рд╕рдм рд╕рдм рдореЗрдВ, рдмрд╣реБрдд рдЕрд╡рд┐рд╢реНрд╡рд╕рдиреАрдпред


рдЖрдк рдирд┐рд╕реНрд╕рдВрджреЗрд╣, рдХреЗрд╡рд▓ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рдЕрдкрдиреА рдореИрдкрд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдПрдХ рдЕрдиреНрдп рдСрдмреНрдЬреЗрдХреНрдЯ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╛ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрдкрдиреЗ рд╣рд╛рдереЛрдВ рд╕реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЪреБрди рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдХреБрдЫ Tuple рдореЗрдВ рдЗрдХрдЯреНрдард╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рджрд░рдЕрд╕рд▓, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрдм рдЬреНрдпрд╛рджрд╛рддрд░ рдЬрдЧрд╣реЛрдВ рдкрд░ рд╣рдо рдРрд╕рд╛ рд╣реА рдХрд░рддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдлрд┐рд░ рднреА рдореИрдВ рдЕрдкрдиреЗ рд╣рд╛рдереЛрдВ рд╕реЗ рдЪрдпрди рдирд╣реАрдВ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛, рди рдХрд┐ рдирдХрд▓ рдХреА рдирдХрд▓ рдХрд░рдирд╛ред



рднрд╛рдЧ рддреАрди рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд▓реЗрдХрд┐рди рдирд┐рд╖реНрдХреНрд░рд┐рдп рд╕рдорд╛рдзрд╛рдиред


рдпрджрд┐ рдЖрдк рдереЛрдбрд╝рд╛ рдФрд░ рд╕реЛрдЪрддреЗ рд╣реИрдВ, рддреЛ рдмрд╣реБрдд рдЬрд▓реНрджреА рдЬрд╡рд╛рдм рдореЗрд░реЗ рджрд┐рдорд╛рдЧ рдореЗрдВ рдЖрддрд╛ рд╣реИ - рдЖрдкрдХреЛ рдЗрдВрдЯрд░рдлреЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдлрд┐рд░ рдмрд╕ рдШреЛрд╖рдгрд╛ рдХрд░рддреЗ рд╣реИрдВ


 public interface MsisdnAndBalance { String getMsisdn(); long getBalance(); } 

рдФрд░ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ


 MsisdnAndBalance card = cardDAO.partialGet(cardId, ...); 

рдФрд░ рд╡рд╣ рд╕рдм рд╣реИред рдХреБрдЫ рднреА рдЕрддрд┐рд░рд┐рдХреНрдд рдордд рдХрд╣реЛред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдХреЛрдЯрд▓рд┐рди / рджрд╕ / рдЧрд░реНрдн рдХреЗ рд╕рдВрдХреНрд░рдордг рдХреЗ рд╕рд╛рде, рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЗрд╕ рднрдпрд╛рдирдХ рдкреНрд░рдХрд╛рд░ рдХреЛ рднреА рд╕рдорд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдпрд╣рд╛рдВ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд┐рдВрджреБ рдЕрднреА рднреА рдЫреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реИред partialGet рдХреЛ рдХреНрдпрд╛ рддрд░реНрдХ рджрд┐рдП рдЬрд╛рдиреЗ рдЪрд╛рд╣рд┐рдП? рдереЛрдВрдЧреНрд╕, рдкрд╣рд▓реЗ рдХреА рддрд░рд╣, рдЕрдм рдФрд░ рдорд╣рд╕реВрд╕ рдирд╣реАрдВ рдХрд░рддреЗ, рдХреНрдпреЛрдВрдХрд┐ рдЧрд▓рддрд┐рдпрд╛рдБ рдХрд░рдиреЗ рдФрд░ рдЧрд▓рдд рдХреНрд╖реЗрддреНрд░ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЬреЛрдЦрд┐рдо рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реИред рдФрд░ рдореИрдВ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдЖрдк рдХрд┐рд╕реА рддрд░рд╣ рд╕рдХреНрд╖рдо рд╣реЛрдВ


 MsisdnAndBalance card = cardDAO.partialGet(cardId, MsisdnAndBalance.class); 

рдпрд╛ рд╕рдВрд╢реЛрдзрд┐рдд рдЬреЗрдирд░рд┐рдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХреЛрдЯрд▓рд┐рди рдкрд░ рднреА рдмреЗрд╣рддрд░


 val card = cardDAO.paritalGet<MsisdnAndBalance>(cardId) 

рдПрд╣, рдПрдХ рд╡рд┐рд╕реНрдлреЛрдЯред рджрд░рдЕрд╕рд▓, рдЖрдЧреЗ рдХреА рдкреВрд░реА рдХрд╣рд╛рдиреА рдЗрд╕ рд╡рд┐рдХрд▓реНрдк рдХреЗ рдХреНрд░рд┐рдпрд╛рдиреНрд╡рдпрди рдХреА рд╣реИред



рднрд╛рдЧ рдЪрд╛рд░ рдмрд╛рдИрдЯреЗрдХреЛрдб рдХреЗ рд░рд╛рд╕реНрддреЗ рдореЗрдВ


рдореБрдЦреНрдп рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рддрд░реАрдХреЗ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╕реЗ рдЖрддреЗ рд╣реИрдВ, рдФрд░ рдПрдиреЛрдЯреЗрд╢рди рдлрд╝реАрд▓реНрдб рдХреЗ рдКрдкрд░ рд╣реИрдВред рдФрд░ рд╣рдореЗрдВ рдЗрдиреНрд╣реАрдВ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рд╡рд┐рдзрд┐рдпреЛрдВ рджреНрд╡рд╛рд░рд╛ рдЦреЛрдЬрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдкрд╣рд▓рд╛ рдФрд░ рд╕рдмрд╕реЗ рд╕реНрдкрд╖реНрдЯ рд╡рд┐рдЪрд╛рд░ рдорд╛рдирдХ рдЬрд╛рд╡рд╛ рдмреАрди рд╕рдореНрдореЗрд▓рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИред рдФрд░ рддреБрдЪреНрдЫ рдЧреБрдгреЛрдВ рдХреЗ рд▓рд┐рдП, рдпрд╣ рднреА рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдпрд╣ рдмрд╣реБрдд рдЕрд╕реНрдерд┐рд░ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрд╣ рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдореЗрдВ рдПрдХ рд╡рд┐рдзрд┐ рдХрд╛ рдирд╛рдо рдмрджрд▓рдиреЗ рдХреЗ рд▓рд╛рдпрдХ рд╣реИ (рд╡реИрдЪрд╛рд░рд┐рдХ рд░рд┐рдлреИрдХреНрдЯрд┐рдВрдЧ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ), рдХреНрдпреЛрдВрдХрд┐ рд╕рдм рдХреБрдЫ рддреБрд░рдВрдд рдЕрд▓рдЧ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрдХреНрд╖рд╛рдУрдВ рдореЗрдВ рддрд░реАрдХреЛрдВ рдХрд╛ рдирд╛рдо рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рдЪрд╛рд░ рдХрд╛рдлреА рд╕реНрдорд╛рд░реНрдЯ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдЧрдЯрд░ рдерд╛ рдФрд░ рдЖрдкрдХреЛ рдлрд╝реАрд▓реНрдб рдХрд╛ рдирд╛рдо рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдФрд░ рдЗрд╕реА рддрд░рд╣ рдХреЗ рд╕рдорд╛рдзрд╛рди рд╕реЗ рдЦреЗрддреЛрдВ рдХрд╛ рджреЛрд╣рд░рд╛рд╡ рд╣реЛрддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЕрдЧрд░ рдореБрдЭреЗ рдЕрдкрдиреЗ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдореЗрдВ getClientId() рд╡рд┐рдзрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдореИрдВ рдЗрд╕реЗ рдХреЗрд╡рд▓ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛


 public class Client implements HasClientId { private Long id; @Override public Long getClientId() { return id; } } 

 public class Card implements HasClientId { private Client client; @Override public Long getClientId() { return client.getId(); } } 

рдФрд░ рдореБрдЭреЗ рдЦреЗрддреЛрдВ рдХреА рдирдХрд▓ рдХрд░рдиреА рд╣реИред рдФрд░ Client рдореЗрдВ рджреЛрдиреЛрдВ id рдФрд░ clientId рдЦреАрдВрдЪреЗрдВ, рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рдмрдЧрд▓ рд╡рд╛рд▓реЗ рдореИрдк рдореЗрдВ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ clientId ред рдФрд░ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдпрд╣ рд╕рдм рдирд╣реАрдВ рдЫреЛрдбрд╝рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдореБрдЭреЗ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЧреИрд░-рддреБрдЪреНрдЫ рддрд░реНрдХ рдХреЗ рд╕рд╛рде рдЧреЗрдЯрд░реНрд╕ рднреА рдЪрд╛рд╣рд┐рдП, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП


 public class Card implements HasBalance { private Account account; private Client client; public long getBalance() { if (account != null) return account.getBalance(); else return client.getDefaultAccount().getBalance(); } } 

рддреЛ рдирд╛рдо рд╕реЗ рдЦреЛрдЬ рдХрд░рдиреЗ рдХреЗ рд╡рд┐рдХрд▓реНрдк рдХреА рдЕрдм рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдЖрдкрдХреЛ рдХреБрдЫ рдЕрдзрд┐рдХ рдореБрд╢реНрдХрд┐рд▓ рд╣реИред


рдЕрдЧрд▓рд╛ рд╡рд┐рдХрд▓реНрдк рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдкрд╛рдЧрд▓ рдерд╛ рдФрд░ рдореЗрд░реЗ рд╕рд┐рд░ рдореЗрдВ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдирд╣реАрдВ рд░рд╣рд╛, рд▓реЗрдХрд┐рди рдХрд╣рд╛рдиреА рдХреА рдкреВрд░реНрдгрддрд╛ рдХреЗ рд▓рд┐рдП рдореИрдВ рдЗрд╕рдХрд╛ рднреА рд╡рд░реНрдгрди рдХрд░реВрдВрдЧрд╛ред рдкрд╛рд░реНрд╕рд┐рдВрдЧ рд╕реНрдЯреЗрдЬ рдкрд░, рд╣рдо рдПрдХ рдЦрд╛рд▓реА рдЗрдХрд╛рдИ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдмрд╕ рдЦреЗрддреЛрдВ рдореЗрдВ рдХреБрдЫ рдорд╛рди рд▓рд┐рдЦрддреЗ рд╣реБрдП рдореБрдбрд╝ рдЬрд╛рддреЗ рд╣реИрдВ, рдФрд░ рдЙрд╕рдХреЗ рдмрд╛рдж рд╣рдореЗрдВ рдЧреЗрдЯрд░реНрд╕ рдорд┐рд▓рддреЗ рд╣реИрдВ рдФрд░ рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдмрджрд▓ рдЧрдпрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВред рдЗрд╕рд▓рд┐рдП рд╣рдо рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ name рдлрд╝реАрд▓реНрдб рдореЗрдВ рд░рд┐рдХреЙрд░реНрдб рд╕реЗ getClientId рдХрд╛ рдорд╛рди рдирд╣реАрдВ рдмрджрд▓рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд░рд┐рдХреЙрд░реНрдб id рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╕реНрдерд┐рддрд┐ рдЬрдм рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░ рдХреЗ isActive() = i_active != 0 рдФрд░ рдлрд╝реАрд▓реНрдб (рдЬреИрд╕реЗ рдХрд┐ isActive() = i_active != 0 ) рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдпрд╣рд╛рдВ рд╣реИрдВред рд▓реЗрдХрд┐рди рдХрдо рд╕реЗ рдХрдо рддреАрди рдЧрдВрднреАрд░ рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реИрдВ (рд╢рд╛рдпрдж рдЕрдзрд┐рдХ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рдЖрдЧреЗ рдирд╣реАрдВ рд╕реЛрдЪрд╛ рд╣реИ)ред


  1. рдЗрд╕ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЗ рд╕рд╛рде рд╕рд╛рд░ рдХреЗ рд▓рд┐рдП рд╕реНрдкрд╖реНрдЯ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдпрджрд┐ "рд╕рдВрдмрдВрдзрд┐рдд" рдлрд╝реАрд▓реНрдб рдирд╣реАрдВ рдмрджрд▓рд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ рдЧреЗрдЯреНрдЯрд░ рд╕реЗ "рдЙрд╕реА" рдореВрд▓реНрдп рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред "рдПрдХ рд╕рдорд╛рди" - рд╣рдордиреЗ рдЬреЛ рддреБрд▓рдирд╛ рдСрдкрд░реЗрдЯрд░ рдЪреБрдирд╛ рд╣реИ, рдЙрд╕рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗред == рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ (рдЕрдиреНрдпрдерд╛ рдХреБрдЫ getAsInt() = Integer.parseInt(strField)) рдХрд╛рдо рдХрд░рдирд╛ рдмрдВрдж рдХрд░ рджреЗрдЧрд╛ getAsInt() = Integer.parseInt(strField)) ред рдмрд░рд╛рдмрд░реА рдкрд░ рд░рд╣рддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдЕрдЧрд░ рдЧреЗрдЯреНрдЯрд░ рдкреНрд░рддреНрдпреЗрдХ рдХреЙрд▓ рдкрд░ рдлрд╝реАрд▓реНрдбреНрд╕ рджреНрд╡рд╛рд░рд╛ рдЙрддреНрдкрдиреНрди рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХреА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдХрд╛рдИ рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рддреЛ рдЙрд╕рдХреЗ рдкрд╛рд╕ equals рдУрд╡рд░рд░рд╛рдЗрдб рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред
  2. рд╕рдВрдкреАрдбрд╝рди рдореИрдкрд┐рдВрдЧред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП int -> boolean рдКрдкрд░ рдХреЗ рд╕рд╛рдеред рдпрджрд┐ рд╣рдо 0 рдФрд░ 1 рдХреЗ рдореВрд▓реНрдпреЛрдВ рдкрд░ рдЬрд╛рдБрдЪ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдПрдХ рдмрджрд▓рд╛рд╡ рджреЗрдЦреЗрдВрдЧреЗред рд▓реЗрдХрд┐рди рдЕрдЧрд░ рекреж рдФрд░ рекреи рдкрд░ рд╣реИрдВ, рддреЛ рджреЛрдиреЛрдВ рдмрд╛рд░ рд╣рдо рд╕рдЪ рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВред
  3. рдЧреЗрдЯрд░реНрд╕ рдореЗрдВ рдЬрдЯрд┐рд▓ рдХрдиреНрд╡рд░реНрдЯрд░реНрд╕ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдЦреЗрддреЛрдВ рдореЗрдВ рдХреБрдЫ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдкрд░ рднрд░реЛрд╕рд╛ рдХрд░рддреЗ рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкреНрд░рд╛рд░реВрдк)ред рдФрд░ рд╣рдорд╛рд░реЗ рдЙрддреНрдкрдиреНрди рдЖрдВрдХрдбрд╝реЛрдВ рдкрд░ рд╡реЗ рдЕрдкрд╡рд╛рджреЛрдВ рдХреЛ рдлреЗрдВрдХ рджреЗрдВрдЧреЗред

рддреЛ рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рд╡рд┐рдХрд▓реНрдк рднреА рдХрд╛рдо рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реИред


рдкреВрд░реА рдмрд╛рдд рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ, рдореИрдВрдиреЗ рд╢реБрд░реВ рдореЗрдВ рдордЬрд╛рдХ рдореЗрдВ "рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ, рдирдлреАрдЧ рд╡рд╛рдХреНрдпрд╛рдВрд╢ рдХрд╣рд╛, рдпрд╣ рдмрд╛рдИрдЯреЗрдХреЛрдб рдХреЛ рджреЗрдЦрдирд╛ рдЖрд╕рд╛рди рд╣реИ, рд╕рдм рдХреБрдЫ рд╡рд╣рд╛рдВ рд▓рд┐рдЦрд╛ рд╣реИред" рдЙрд╕ рд╕рдордп, рдореБрдЭреЗ рдпрд╣ рднреА рдПрд╣рд╕рд╛рд╕ рдирд╣реАрдВ рдерд╛ рдХрд┐ рдпрд╣ рд╡рд┐рдЪрд╛рд░ рдореБрдЭреЗ рдирд┐рдЧрд▓ рдЬрд╛рдПрдЧрд╛, рдФрд░ рд╕рдм рдХреБрдЫ рдХрд┐рддрдирд╛ рджреВрд░ рдЪрд▓рд╛ рдЬрд╛рдПрдЧрд╛ред



рднрд╛рдЧ рдкрд╛рдВрдЪ рдмрд╛рдЗрдЯреЗрдХреЛрдб рдХреНрдпрд╛ рд╣реИ рдФрд░ рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ


new #4, dup, invokespecial #5, areturn
рдпрджрд┐ рдЖрдк рд╕рдордЭрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣рд╛рдБ рдХреНрдпрд╛ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдпрд╣ рдХреЛрдб рдХреНрдпрд╛ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдЖрдк рдЕрдЧрд▓реЗ рднрд╛рдЧ рдХреЛ рдЫреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред


рдЕрд╕реНрд╡реАрдХрд░рдг 1. рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдЖрдЧреЗ рдХреА рдХрд╣рд╛рдиреА рдХреЛ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдХрдо рд╕реЗ рдХрдо рдПрдХ рдмреБрдирд┐рдпрд╛рджреА рд╕рдордЭ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдЬрд╛рд╡рд╛ рдмрд╛рдпрдЯреЗрдХреЛрдб рдХреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреБрдЫ рдкреИрд░рд╛рдЧреНрд░рд╛рдл рд▓рд┐рдЦреВрдВрдЧрд╛ред рдХрд┐рд╕реА рднреА рддрд░рд╣ рд╕реЗ рдкреВрд░рд╛ рд╣реЛрдиреЗ рдХрд╛ рдирд╛рдЯрдХ рдирд╣реАрдВред


рдЕрд╕реНрд╡реАрдХрд░рдг 2. рдпрд╣ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рд╢рд░реАрд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣реЛрдЧрд╛ред рди рддреЛ рдирд┐рд░рдВрддрд░ рдкреВрд▓ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ, рди рд╣реА рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХрдХреНрд╖рд╛ рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ, рдФрд░ рди рд╣реА рдЦреБрдж рдХреА рдШреЛрд╖рдгрд╛рдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ, рдореИрдВ рдПрдХ рд╢рдмреНрдж рднреА рдХрд╣реВрдВрдЧрд╛ред


рдореБрдЦреНрдп рдЪреАрдЬ рдЬрд┐рд╕реЗ рдЖрдкрдХреЛ рдмрд╛рдпрдЯреЗрдХреЛрдб рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рдордЭрдирд╛ рд╣реЛрдЧрд╛, рд╡рд╣ рдЬрд╛рд╡рд╛ рд╕реНрдЯреИрдХ рд╡рд░реНрдЪреБрдЕрд▓ рдорд╢реАрди рдХреЗ рд▓рд┐рдП рдХреЛрдбрд╛рдВрддрд░рдХ рд╣реИред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ рд▓рд┐рдП рддрд░реНрдХ рд╕реНрдЯреИрдХ рд╕реЗ рд▓рд┐рдП рдЧрдП рд╣реИрдВ рдФрд░ рдирд┐рд░реНрджреЗрд╢реЛрдВ рд╕реЗ рд░рд┐рдЯрд░реНрди рдорд╛рди рд╕реНрдЯреИрдХ рдкрд░ рд╡рд╛рдкрд╕ рдзрдХреЗрд▓ рджрд┐рдП рдЧрдП рд╣реИрдВред рдЗрд╕ рджреГрд╖реНрдЯрд┐ рд╕реЗ, рд╣рдо рдпрд╣ рдХрд╣ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдмрд╛рдИрдЯрдХреЛрдб рд░рд┐рд╡рд░реНрд╕ рдкреЛрд▓рд┐рд╢ рдЕрдВрдХрди рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ ред рд╕реНрдЯреИрдХ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╡рд┐рдзрд┐ рдореЗрдВ рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдХреА рдПрдХ рд╕рд░рдгреА рднреА рд╣реИред рд╡рд┐рдзрд┐ рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд░рдиреЗ рдкрд░, this рдкрджреНрдзрддрд┐ рдХреЗ рд╕рднреА рддрд░реНрдХреЛрдВ рдХреЛ рдЗрд╕рдореЗрдВ рд▓рд┐рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рджреМрд░рд╛рди рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдЬрдорд╛ рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВред рдпрд╣рд╛рдБ рдПрдХ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг рд╣реИред


 public class Foo { private int bar; public int updateAndReturn(long baz, String str) { int result = (int) baz; result += str.length(); bar = result; return result; } } 

рдореИрдВ рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдЯрд┐рдкреНрдкрдгреА рд▓рд┐рдЦреВрдВрдЧрд╛


 # [(<local_variable_index>:<actual_value>)*], [(<value_on_stack>)*] 

рдмрд╛рдИрдВ рдУрд░ рдвреЗрд░ рдХреЗ рдКрдкрд░ред


 public int updateAndReturn(long, java.lang.String); Code: # [0:this, 1:long baz, 3:str], () 0: lload_1 # [0:this, 1:long baz, 3:str], (long baz) 1: l2i # [0:this, 1:long baz, 3:str], (int baz) 2: istore 4 # [0:this, 1:long baz, 3:str, 4:int baz], () 4: iload 4 # [0:this, 1:long baz, 3:str, 4:int baz], (int baz) 6: aload_3 # [0:this, 1:long baz, 3:str, 4:int baz], (str, int baz) 7: invokevirtual #2 // Method java/lang/String.length:()I # [0:this, 1:long baz, 3:str, 4:int baz], (length(str), int baz) 10: iadd # [0:this, 1:long baz, 3:str, 4:int baz], (length(str) + int baz) 11: istore 4 # [0:this, 1:long baz, 3:str, 4:length(str) + int baz], () 13: aload_0 # [0:this, 1:long baz, 3:str, 4:length(str) + int baz], (this) 14: iload 4 # [0:this, 1:long baz, 3:str, 4:length(str) + int baz], (length(str) + int baz, this) 16: putfield #3 // Field bar:I # [0:this, 1:long baz, 3:str, 4:length(str) + int baz], (),     bar 19: iload 4 # [0:this, 1:long baz, 3:str, 4:length(str) + int baz], (length(str) + int baz) 21: ireturn #  int   ,       

рдмрд╣реБрдд рд╕рд╛рд░реЗ рдирд┐рд░реНрджреЗрд╢ рд╣реИрдВред рдкреВрд░реА рд╕реВрдЪреА рдХреЛ JVMS рдХреЗ рдЫрдареЗ рдЕрдзреНрдпрд╛рдп рдореЗрдВ рджреЗрдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ , рд╡рд┐рдХрд┐рдкреАрдбрд┐рдпрд╛ рдкрд░ рдПрдХ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд░рд┐рдЯреЗрд▓рд┐рдВрдЧ рд╣реИ ред рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдирд┐рд░реНрджреЗрд╢ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рджреВрд╕рд░реЗ рдХреА рдирдХрд▓ рдХрд░рддреЗ рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, int рдХреЗ рд▓рд┐рдП lload рдФрд░ рд▓рдВрдмреЗ рд╕рдордп рдХреЗ рд▓рд┐рдП lload )ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдкрд╣рд▓реЗ 4 рд╕реНрдерд╛рдиреАрдп рдЪрд░реЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЙрдирдХреЗ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдкрд░ рдкреНрд░рдХрд╛рд╢ рдбрд╛рд▓рд╛ рдЧрдпрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╡рд╣рд╛рдБ lload_1 рдФрд░ рдпрд╣ рддрд░реНрдХ рдХреЛ рдмрд┐рд▓реНрдХреБрд▓ рд╕реНрд╡реАрдХрд╛рд░ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рд┐рд░реНрдл lload ред рдпрд╣ рдПрдХ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдХреА рд╕рдВрдЦреНрдпрд╛ рд▓реЗ рдЬрд╛рдПрдЧрд╛ред рдКрдкрд░ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдПрдХ рд╕рдорд╛рди iload )ред


рд╡рд┐рд╢реНрд╡ рд╕реНрддрд░ рдкрд░, рд╣рдо рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рдореВрд╣реЛрдВ рдореЗрдВ рд░реБрдЪрд┐ рд▓реЗрдВрдЧреЗ:


  1. *load* , *store* - рдПрдХ рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдХреЛ рдкрдврд╝реЗрдВ / рд▓рд┐рдЦреЗрдВ
  2. рдЗрдВрдбреЗрдХреНрд╕ рджреНрд╡рд╛рд░рд╛ рдПрдХ *aload , *aload - рдкрдврд╝реЗрдВ / рд▓рд┐рдЦреЗрдВ
  3. getfield , putfield - read / write field
  4. getstatic , putstatic - рд╕реНрдЯреИрдЯрд┐рдХ рдлреАрд▓реНрдб рдХреЛ рдкрдврд╝реЗрдВ / рд▓рд┐рдЦреЗрдВ
  5. checkcast - рдСрдмреНрдЬреЗрдХреНрдЯ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдмреАрдЪ рдХрд╛рд╕реНрдЯред рдЬрд░реВрд░рдд рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЯрд╛рдЗрдк рдХрд┐рдП рдЧрдП рдорд╛рди рд╕реНрдЯреИрдХ рдкрд░ рдФрд░ рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдореЗрдВ рд╣реЛрддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдКрдкрд░ рдХрд▓рд╛рдХрд╛рд░реЛрдВ рдХреА рд▓рдВрдмреА рдЕрд╡рдзрд┐ рдХреЗ рд▓рд┐рдП l2i рдерд╛ -> intред
  6. invoke* - рд╡рд┐рдзрд┐ рдХреЙрд▓
  7. *return - рдорд╛рди рд▓реМрдЯрд╛рдПрдВ рдФрд░ рд╡рд┐рдзрд┐ рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓реЗрдВ


рднрд╛рдЧ рдЫрдГ рдореБрдЦреНрдп


рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЬреЛ рдЗрд╕ рддрд░рд╣ рдХреЗ рд▓рдВрдмреЗ рдкрд░рд┐рдЪрдп рд╕реЗ рдЪреВрдХ рдЧрдП, рд╕рд╛рде рд╣реА рд╕рд╛рде рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдореВрд▓ рд╕рдорд╕реНрдпрд╛ рдФрд░ рдХрд╛рд░рдг рд╕реЗ рдзреНрдпрд╛рди рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╕рдорд╕реНрдпрд╛ рдХреЛ рдФрд░ рдЕрдзрд┐рдХ рд╕рдЯреАрдХ рд░реВрдк рд╕реЗ рддреИрдпрд╛рд░ рдХрд░рддреЗ рд╣реИрдВред


рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рд╣рд╛рде рдкрд░ рдПрдХ java.lang.reflect.Method рдЙрджрд╛рд╣рд░рдг рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП, рд╕рднреА рдЧреИрд░-рд╕реНрдерд┐рд░ рдХреНрд╖реЗрддреНрд░реЛрдВ (рджреЛрдиреЛрдВ рд╡рд░реНрддрдорд╛рди рдФрд░ рд╕рднреА рдиреЗрд╕реНрдЯреЗрдб рдСрдмреНрдЬреЗрдХреНрдЯ) рдХреА рд╕реВрдЪреА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдирдХреЗ рд░реАрдбрд┐рдВрдЧ (рд╕реАрдзреЗ рдпрд╛ рдЯреНрд░рд╛рдВрд╕реЗрдЯрд┐рд╡) рдЗрд╕ рдкрджреНрдзрддрд┐ рдХреЗ рдЕрдВрджрд░ рд╣реЛрдВрдЧреЗред

рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдРрд╕реА рд╡рд┐рдзрд┐ рдХреЗ рд▓рд┐рдП


 public long getBalance() { Account acc; if (account != null) acc = account; else acc = client.getDefaultAccount(); return acc.getBalance(); } 

рдЖрдкрдХреЛ рджреЛ рдлрд╝реАрд▓реНрдбреНрд╕ рдХреА рдПрдХ рд╕реВрдЪреА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ: account.balance ред client.defaultAccount.balance рдФрд░ client.defaultAccount.balance ред


рдореИрдВ рд▓рд┐рдЦреВрдВрдЧрд╛, рдпрджрд┐ рд╕рдВрднрд╡ рд╣реЛ рддреЛ, рдПрдХ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рд╕рдорд╛рдзрд╛рдиред рд▓реЗрдХрд┐рди рдПрдХ-рджреЛ рд╕реНрдерд╛рдиреЛрдВ рдкрд░ рдЖрдкрдХреЛ рд╕рд╛рдорд╛рдиреНрдп рд╕рдорд╕реНрдпрд╛, рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЗ рд╕рдорд╛рдзрд╛рди рдХреЗ рд▓рд┐рдП рдореВрд▓ рд╕рдорд╕реНрдпрд╛ рдХреЗ рдЬреНрдЮрд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рдЖрдкрдХреЛ рд╡рд┐рдзрд┐ рдирд┐рдХрд╛рдп рдХрд╛ рдмрд╛рдпрдЯреЗрдХрдХреЛрдб рд╕реНрд╡рдпрдВ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рдЖрдк рд╕реАрдзреЗ рдЬрд╛рд╡рд╛ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдРрд╕рд╛ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗред рд▓реЗрдХрд┐рди рдХрдм рд╕реЗ рдЪреВрдВрдХрд┐ рд╡рд┐рдзрд┐ рдореВрд▓ рд░реВрдк рд╕реЗ рдХреБрдЫ рд╡рд░реНрдЧ рдХреЗ рдЕрдВрджрд░ рдореМрдЬреВрдж рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╕реНрд╡рдпрдВ рдХрдХреНрд╖рд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реИред рд╡рд┐рд╢реНрд╡ рд╕реНрддрд░ рдкрд░, рдореБрдЭреЗ рджреЛ рд╡рд┐рдХрд▓реНрдк рдкрддрд╛ рд╣реИрдВ: рдХреНрд▓рд╛рд╕ рд▓реЛрдбрд┐рдВрдЧ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рд╡реЗрдЬ рдФрд░ рдкрд╣рд▓реЗ рд╕реЗ рдкрдврд╝реА рд╣реБрдИ byte[] рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯ рдХрд░рддрд╛ рд╣реИ, рдпрд╛ рдбрд┐рд╕реНрдХ рдкрд░ ClassName.class рдлрд╛рдЗрд▓ ClassName.class рдФрд░ рдЗрд╕реЗ рдкрдврд╝рддрд╛ рд╣реИред рд╕рд╛рдорд╛рдиреНрдп рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рд╕реНрддрд░ рдкрд░ рд▓реЛрдбрд┐рдВрдЧ рдХрд╛ рдЕрд╡рд░реЛрдзрди рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЖрдкрдХреЛ рдпрд╛ рддреЛ jagagent рдХрдиреЗрдХреНрдЯ рдХрд░рдиреЗ рдпрд╛ рдХрд╕реНрдЯрдо рдХреНрд▓рд╛рд╕рд▓реЙрдбрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдХрд┐рд╕реА рднреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ, jvm / рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрддрд┐рд░рд┐рдХреНрдд рдЪрд░рдгреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдФрд░ рдпрд╣ рдЕрд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИред рдЖрдк рдЗрд╕реЗ рдЖрд╕рд╛рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╕рднреА "рд╕рд╛рдзрд╛рд░рдг" рдХрдХреНрд╖рд╛рдПрдВ рд╣рдореЗрд╢рд╛ рдПрдХреНрд╕рдЯреЗрдВрд╢рди ".class" рдХреЗ рд╕рд╛рде рдПрдХ рд╣реА рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╣реЛрддреА рд╣реИрдВ, рдЬрд┐рд╕ рдкрде рдХреЗ рд▓рд┐рдП рдХреНрд▓рд╛рд╕ рдкреИрдХреЗрдЬ рд╣реИред рд╣рд╛рдВ, рдпрд╣ рдХреБрдЫ рдХрд╕реНрдЯрдо рдХреНрд▓рд╛рд╕ рд▓реЛрдбрд░ рджреНрд╡рд╛рд░рд╛ рд▓реЛрдб рдХрд┐рдП рдЧрдП рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ рдЬреЛрдбрд╝реЗ рдЧрдП рд╡рд░реНрдЧреЛрдВ рдпрд╛ рдХрдХреНрд╖рд╛рдУрдВ рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛, рд▓реЗрдХрд┐рди рд╣рдореЗрдВ jdbc рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рд╡рд┐рд╢реНрд╡рд╛рд╕ рдХреЗ рд╕рд╛рде рдХрд╣ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╕рднреА рд╡рд░реНрдЧреЛрдВ рдХреЛ "рдбрд┐рдлрд╝реЙрд▓реНрдЯ рддрд░реАрдХреЗ рд╕реЗ" рдЬрд╛рд░ рдореЗрдВ рдкреИрдХ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдХреБрд▓:


 private static InputStream getClassFile(Class<?> clazz) { String file = clazz.getName().replace('.', '/') + ".class"; ClassLoader cl = clazz.getClassLoader(); if (cl == null) return ClassLoader.getSystemResourceAsStream(file); else return cl.getResourceAsStream(file); } 

рд╣реБрд░реНрд░реЗ, рдмрд╛рдЗрдЯ рд╕рд░рдгреА рдкрдврд╝реЗрдВред рд╣рдо рдЗрд╕рдХреЗ рд╕рд╛рде рдЖрдЧреЗ рдХреНрдпрд╛ рдХрд░реЗрдВрдЧреЗ? рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ, рдмрд╛рдЗрдЯрдХреЛрдб рдХреЛ рдкрдврд╝рдиреЗ / рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд╛рд╡рд╛ рдореЗрдВ рдХрдИ рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╣реИрдВ, рд▓реЗрдХрд┐рди рдПрдПрд╕рдПрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдЖрдорддреМрд░ рдкрд░ рд╕рдмрд╕реЗ рдирд┐рдЪрд▓реЗ рд╕реНрддрд░ рдХреЗ рдХрд╛рдо рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЙрдЪреНрдЪ рдкреНрд░рджрд░реНрд╢рди рдФрд░ рдСрди-рдж-рдлреНрд▓рд╛рдИ рдСрдкрд░реЗрд╢рди рдХреЗ рд▓рд┐рдП рддреЗрдЬ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╡рд┐рдЬрд╝рд┐рдЯрд░ рдПрдкреАрдЖрдИ рд╡рд╣рд╛рдВ рдореБрдЦреНрдп рд╣реИ - рдПрд╕рдПрд╕рдПрдо рдХреНрд░рдорд┐рдХ рд░реВрдк рд╕реЗ рдХрдХреНрд╖рд╛ рдХреЛ рдкрдврд╝рддрд╛ рд╣реИ рдФрд░ рдЙрдЪрд┐рдд рддрд░реАрдХреЛрдВ рдХреЛ рдЦреАрдВрдЪрддрд╛ рд╣реИ


 public abstract class ClassVisitor { public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {...} public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {...} public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {...} ... } public abstract class MethodVisitor { protected MethodVisitor mv; public MethodVisitor(final int api, final MethodVisitor mv) { ... this.mv = mv; } public void visitJumpInsn(int opcode, Label label) { if (mv != null) { mv.visitJumpInsn(opcode, label); } } ... } 

рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдЙрд╕рдХреЗ рд╣рд┐рдд рдХреЗ рддрд░реАрдХреЛрдВ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдФрд░ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг / рдкрд░рд┐рд╡рд░реНрддрди рддрд░реНрдХ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдордВрддреНрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред MethodVisitor рдХреЗ рдЙрджрд╛рд╣рд░рдг рдкрд░ рдЕрд▓рдЧ рд╕реЗ, рдореИрдВ рдЗрд╕ рддрдереНрдп рдкрд░ рдзреНрдпрд╛рди рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ рдХрд┐ рд╕рднреА рдЖрдЧрдВрддреБрдХреЛрдВ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рдордВрдбрд▓ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИред


рдореБрдЦреНрдп рдПрдкреАрдЖрдИ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдмреЙрдХреНрд╕ рдХреЗ рдмрд╛рд╣рд░ рдПрдХ рдЯреНрд░реА рдПрдкреАрдЖрдИ рднреА рд╣реИред рдпрджрд┐ рдХреЛрд░ рдПрдкреАрдЖрдИ рдПрд╕рдПрдПрдХреНрд╕ рдкрд╛рд░реНрд╕рд░ рдХрд╛ рдПрдХ рдПрдирд╛рд▓реЙрдЧ рд╣реИ, рддреЛ рдЯреНрд░реА рдПрдкреАрдЖрдИ рдбреЛрдо рдХрд╛ рдПрдХ рдПрдирд╛рд▓реЙрдЧ рд╣реИред рд╣рдореЗрдВ рдПрдХ рдРрд╕реА рд╡рд╕реНрддреБ рдорд┐рд▓рддреА рд╣реИ рдЬрд┐рд╕рдХреЗ рдЕрдВрджрд░ рд╡рд░реНрдЧ / рд╡рд┐рдзрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рднреА рдЬрд╛рдирдХрд╛рд░реА рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реЛрддреА рд╣реИ рдФрд░ рд╣рдо рдЗрд╕рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рдХрд┐рд╕реА рднреА рд╕реНрдерд╛рди рдкрд░ рдЫрд▓рд╛рдВрдЧ рдХреЗ рд╕рд╛рде рдЪрд╛рд╣рддреЗ рд╣реИрдВред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ рдПрдкреАрдЖрдИ рдПрдХ *Visitor рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИ рдЬреЛ visit* рдЕрдВрджрд░ visit* рддрд░реАрдХреЗ рдмрд╕ рдЬрд╛рдирдХрд╛рд░реА рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИред рд▓рдЧрднрдЧ рд╕рднреА рддрд░реАрдХреЗ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддреЗ рд╣реИрдВ:


 public class MethodNode extends MethodVisitor { @Override public void visitJumpInsn(final int opcode, final Label label) { instructions.add(new JumpInsnNode(opcode, getLabelNode(label))); } ... } 

рдЕрдм рд╣рдо рдЕрдВрдд рдореЗрдВ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рд▓рд┐рдП рд╡рд┐рдзрд┐ рд▓реЛрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


 private static class AnalyzerClassVisitor extends ClassVisitor { private final String getterName; private final String getterDesc; private MethodNode methodNode; public AnalyzerClassVisitor(Method getter) { super(ASM6); this.getterName = getter.getName(); this.getterDesc = getMethodDescriptor(getter); } public MethodNode getMethodNode() { if (methodNode == null) throw new IllegalStateException(); return methodNode; } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { //      if (!name.equals(getterName) || !desc.equals(getterDesc)) return null; return new AnalyzerMethodVisitor(access, name, desc, signature, exceptions); } private class AnalyzerMethodVisitor extends MethodVisitor { public AnalyzerMethodVisitor(int access, String name, String desc, String signature, String[] exceptions) { super(ASM6, new MethodNode(ASM6, access, name, desc, signature, exceptions)); } @Override public void visitEnd() { //     ,     MethodVisitor    if (methodNode != null) throw new IllegalStateException(); methodNode = (MethodNode) mv; } } } 

рдкреВрд░реНрдг рдХреЛрдб рдкрдврд╝рдиреЗ рдХреА рд╡рд┐рдзрд┐ред

MethodNode рд╕реАрдзреЗ рдирд╣реАрдВ рд▓реМрдЯрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдмрд▓реНрдХрд┐ рдПрдХреНрд╕ рдХреА рдПрдХ рдЬреЛрдбрд╝реА рдХреЗ рд╕рд╛рде рдПрдХ рдЖрд╡рд░рдгред рдЦреЗрддреЛрдВ рдХреНрдпреЛрдВрдХрд┐ рд╣рдореЗрдВ рдмрд╛рдж рдореЗрдВ рднреА рдЙрдирдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдмрд┐рдВрджреБ (рдФрд░ рдХреЗрд╡рд▓ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд╡рд┐рдзрд┐) readMethod(Method): MethodInfo ред


 public class MethodReader { public static class MethodInfo { private final String internalDeclaringClassName; private final int classAccess; private final MethodNode methodNode; public MethodInfo(String internalDeclaringClassName, int classAccess, MethodNode methodNode) { this.internalDeclaringClassName = internalDeclaringClassName; this.classAccess = classAccess; this.methodNode = methodNode; } public String getInternalDeclaringClassName() { return internalDeclaringClassName; } public int getClassAccess() { return classAccess; } public MethodNode getMethodNode() { return methodNode; } } public static MethodInfo readMethod(Method method) { Class<?> clazz = method.getDeclaringClass(); String internalClassName = getInternalName(clazz); try (InputStream is = getClassFile(clazz)) { ClassReader cr = new ClassReader(is); AnalyzerClassVisitor cv = new AnalyzerClassVisitor(internalClassName, method); cr.accept(cv, SKIP_DEBUG | SKIP_FRAMES); return new MethodInfo(internalClassName, cv.getAccess(), cv.getMethodNode()); } catch (IOException e) { throw new RuntimeException(e); } } private static InputStream getClassFile(Class<?> clazz) { String file = clazz.getName().replace('.', '/') + ".class"; ClassLoader cl = clazz.getClassLoader(); if (cl == null) return ClassLoader.getSystemResourceAsStream(file); else return cl.getResourceAsStream(file); } private static class AnalyzerClassVisitor extends ClassVisitor { private final String className; private final String getterName; private final String getterDesc; private MethodNode methodNode; private int access; public AnalyzerClassVisitor(String internalClassName, Method getter) { super(ASM6); this.className = internalClassName; this.getterName = getter.getName(); this.getterDesc = getMethodDescriptor(getter); } public MethodNode getMethodNode() { if (methodNode == null) throw new IllegalStateException(); return methodNode; } public int getAccess() { return access; } @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { if (!name.equals(className)) throw new IllegalStateException(); this.access = access; } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { if (!name.equals(getterName) || !desc.equals(getterDesc)) return null; return new AnalyzerMethodVisitor(access, name, desc, signature, exceptions); } private class AnalyzerMethodVisitor extends MethodVisitor { public AnalyzerMethodVisitor(int access, String name, String desc, String signature, String[] exceptions) { super(ASM6, new MethodNode(ASM6, access, name, desc, signature, exceptions)); } @Override public void visitEnd() { if (methodNode != null) throw new IllegalStateException(); methodNode = (MethodNode) mv; } } } } 

рдпрд╣ рд╕реАрдзреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рд╣реИред рдЗрд╕реЗ рдХреИрд╕реЗ рдмрдирд╛рдпрд╛ рдЬрд╛рдП? рдкрд╣рд▓рд╛ рд╡рд┐рдЪрд╛рд░ рд╕рднреА getfield рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЛ рджреЗрдЦрдирд╛ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ getfield рдХрд╣рддреА рд╣реИ рдХрд┐ рдпрд╣ рдХреМрди рд╕рд╛ рдлреАрд▓реНрдб рд╣реИ рдФрд░ рдХреМрди рд╕рд╛ рдХреНрд▓рд╛рд╕ рд╣реИред рдЗрд╕реЗ рд╣рдорд╛рд░реА рдХрдХреНрд╖рд╛ рдХреЗ рдЙрди рд╕рднреА рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдорд╛рдирд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬрд╣рд╛рдВ рддрдХ тАЛтАЛрдкрд╣реБрдВрдЪ рдереАред рд▓реЗрдХрд┐рди, рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдпрд╣рд╛рдВ рдкрд╣рд▓реА рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдЕрддрд┐рд░рд┐рдХреНрдд рдкрд░ рдХрдмреНрдЬрд╛ рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИред


 class Foo { private int bar; private int baz; public int test() { return bar + new Foo().baz; } } 

рдЗрд╕ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЗ рд╕рд╛рде, рд╣рдо рдорд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдмрд╛рдЬ рдореИрджрд╛рди рдХреА рдЬрд░реВрд░рдд рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдирд╣реАрдВред рд▓реЗрдХрд┐рди рдлрд┐рд░ рднреА рдпрд╣ рд╕рдорд╕реНрдпрд╛ рдмрдиреА рд░рд╣ рд╕рдХрддреА рд╣реИред рд▓реЗрдХрд┐рди рддрд░реАрдХреЛрдВ рдХреЗ рд╕рд╛рде рдХреНрдпрд╛ рдХрд░рдирд╛ рд╣реИ?


 public class Client implements HasClientId { private Long id; public Long getId() { HasClientId obj = this; return obj.getClientId(); } @Override public Long getClientId() { return id; } } 

рдпрджрд┐ рд╣рдо рдЙрд╕реА рддрд░реАрдХреЗ рд╕реЗ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ рдЬреИрд╕реЗ рд╣рдо рдлрд╝реАрд▓реНрдб рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ getClientId рдирд╣реАрдВ рдорд┐рд▓реЗрдЧрд╛ред рдЗрд╕рдХреЗ рд▓рд┐рдП Client.getClientId рдХреЛрдИ рдХреЙрд▓ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ HasClientId.getClientId рдХреЙрд▓ рдХрд░реЗрдВред рдмреЗрд╢рдХ, рдЖрдк рд╡рд░реНрддрдорд╛рди рдХрдХреНрд╖рд╛ рдХреЗ рд╕рднреА рддрд░реАрдХреЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕рдХреЗ рд╕рднреА рд╕реБрдкрд░рдХреНрд▓рд╛рд╕реЗрд╕ рдФрд░ рд╕рднреА рдЗрдВрдЯрд░рдлреЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╣реИред рддреЛ рдЖрдк рдЧрд▓рддреА рд╕реЗ toString рдкрд░ рдХрдмреНрдЬрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдЗрд╕рдореЗрдВ рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рд╕рднреА рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рд╣реИред


рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдо рдиреЗрд╕реНрдЯреЗрдб рдСрдмреНрдЬреЗрдХреНрдЯ рдкрд░ рднреА рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЧреЗрдЯреНрдЯрд░ рдХреЙрд▓ рдЪрд╛рд╣рддреЗ рд╣реИрдВ


 public class Account { private Client client; public long getClientId() { return client.getId(); } } 

рдФрд░ рдпрд╣рд╛рдБ рдкрд░ Client.getId рдореЗрдердб рдкрд░ рдХреЙрд▓ Account рдХреНрд▓рд╛рд╕ рдХреЗ рд▓рд┐рдП рдмрд┐рд▓рдХреБрд▓ рднреА рд▓рд╛рдЧреВ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред


рдПрдХ рдордЬрдмреВрдд рдЗрдЪреНрдЫрд╛ рдХреЗ рд╕рд╛рде, рдЖрдк рдЕрднреА рднреА рдХреБрдЫ рд╕рдордп рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢реЗрд╖ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рд╣реИрдХ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдмрд╣реБрдд рдЬрд▓реНрджреА рдпрд╣ рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИ рдХрд┐ "рдЪреАрдЬреЗрдВ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдирд╣реАрдВ рдХреА рдЬрд╛рддреА рд╣реИрдВ" рдФрд░ рдЖрдкрдХреЛ рдирд┐рд╖реНрдкрд╛рджрди рдФрд░ рдбреЗрдЯрд╛ рдЖрдВрджреЛрд▓рди рдХреЗ рдкреНрд░рд╡рд╛рд╣ рдХреА рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдирд┐рдЧрд░рд╛рдиреА рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред getfield , this , - this . рдпрд╣рд╛рдБ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ:


 class Client { public long id; } class Account { public long id; public Client client; public long test() { return client.id + new Account().id; } } 

 class Account { public Client client; public long test(); Code: 0: aload_0 1: getfield #2 // Field client:LClient; 4: getfield #3 // Field Client.id:J 7: new #4 // class Account 10: dup 11: invokespecial #5 // Method "<init>":()V 14: getfield #6 // Field id:J 17: ladd 18: lreturn } 

  • 1: getfield this , aload_0 .
  • 4: getfield тАФ , 1: getfield , , , this .
  • 14: getfield . рдХреНрдпреЛрдВрдХрд┐ , ( Account ), this , , 7: new .

, Account.client.id , Account.id тАФ . , , .


тАФ , , aload_0 getfield this , , . , . . тАФ ! -, . MethodNode , ( ). , .. (//) .


:


 public class Analyzer<V extends Value> { public Analyzer(final Interpreter<V> interpreter) {...} public Frame<V>[] analyze(final String owner, final MethodNode m) {...} } 

Analyzer ( Frame , ) . , , , , //etc.


 public abstract class Interpreter<V extends Value> { public abstract V newValue(Type type); public abstract V newOperation(AbstractInsnNode insn) throws AnalyzerException; public abstract V copyOperation(AbstractInsnNode insn, V value) throws AnalyzerException; public abstract V unaryOperation(AbstractInsnNode insn, V value) throws AnalyzerException; public abstract V binaryOperation(AbstractInsnNode insn, V value1, V value2) throws AnalyzerException; public abstract V ternaryOperation(AbstractInsnNode insn, V value1, V value2, V value3) throws AnalyzerException; public abstract V naryOperation(AbstractInsnNode insn, List<? extends V> values) throws AnalyzerException; public abstract void returnOperation(AbstractInsnNode insn, V value, V expected) throws AnalyzerException; public abstract V merge(V v, V w); } 

V тАФ , , . Analyzer , , , . , getfield тАФ , , . , unaryOperation(AbstractInsnNode insn, V value): V , . 1: getfield Value , " client , Client ", 14: getfield " тАФ - , ".


merge(V v, V w): V . , , . рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:


 public long getBalance() { Account acc; if (account != null) acc = account; else acc = client.getDefaultAccount(); return acc.getBalance(); } 

Account.getBalance() . - . . ? merge .


тАФ SuperInterpreter extends Interpreter<SuperValue> ? рдпрд╣ рд╕рд╣реА рд╣реИред SuperValue . тАФ , . , .


 public class Value extends BasicValue { private final Set<Ref> refs; private Value(Type type, Set<Ref> refs) { super(type); this.refs = refs; } } public class Ref { private final List<Field> path; private final boolean composite; public Ref(List<Field> path, boolean composite) { this.path = path; this.composite = composite; } } 

composite . , . , String . String.length() , , name , name.value.length . , length тАФ , , arraylength . ? рдирд╣реАрдВ! тАФ . , , , . , Date , String , Long , . , , .


 class Persion { @JdbcColumn(converter = CustomJsonConverter.class) private PassportInfo passportInfo; } 

PassportInfo . , . , composite . .


 public class Ref { private final List<Field> path; private final boolean composite; public Ref(List<Field> path, boolean composite) { this.path = path; this.composite = composite; } public List<Field> getPath() { return path; } public boolean isComposite() { return composite; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Ref ref = (Ref) o; return Objects.equals(path, ref.path); } @Override public int hashCode() { return Objects.hash(path); } @Override public String toString() { if (path.isEmpty()) return "<[this]>"; else return "<" + path.stream().map(Field::getName).collect(joining(".")) + ">"; } public static Ref thisRef() { return new Ref(emptyList(), true); } public static Optional<Ref> childRef(Ref parent, Field field, Configuration configuration) { if (!parent.isComposite()) return empty(); if (parent.path.contains(field))//    ,   return empty(); List<Field> path = new ArrayList<>(parent.path); path.add(field); return of(new Ref(path, configuration.isCompositeField(field))); } public static Optional<Ref> childRef(Ref parent, Ref child) { if (!parent.isComposite()) return empty(); if (child.path.stream().anyMatch(parent.path::contains))// ,   return empty(); List<Field> path = new ArrayList<>(parent.path); path.addAll(child.path); return of(new Ref(path, child.composite)); } } 

 public class Value extends BasicValue { private final Set<Ref> refs; private Value(Type type, Set<Ref> refs) { super(type); this.refs = refs; } public Set<Ref> getRefs() { return refs; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; if (!super.equals(o)) return false; Value value = (Value) o; return Objects.equals(refs, value.refs); } @Override public int hashCode() { return Objects.hash(super.hashCode(), refs); } @Override public String toString() { return "(" + refs.stream().map(Object::toString).collect(joining(",")) + ")"; } public static Value typedValue(Type type, Ref ref) { return new Value(type, singleton(ref)); } public static Optional<Value> childValue(Value parent, Value child) { Type type = child.getType(); Set<Ref> fields = parent.refs.stream() .flatMap(p -> child.refs.stream().map(c -> childRef(p, c))) .filter(Optional::isPresent) .map(Optional::get) .collect(toSet()); if (fields.isEmpty()) return empty(); return of(new Value(type, fields)); } public static Optional<Value> childValue(Value parent, FieldInsnNode childInsn, Configuration configuration) { Type type = Type.getType(childInsn.desc); Field child = resolveField(childInsn); Set<Ref> fields = parent.refs.stream() .map(p -> childRef(p, child, configuration)) .filter(Optional::isPresent) .map(Optional::get) .collect(toSet()); if (fields.isEmpty()) return empty(); return of(new Value(type, fields)); } public static Value mergeValues(Collection<Value> values) { List<Type> types = values.stream().map(BasicValue::getType).distinct().collect(toList()); if (types.size() != 1) { String typesAsString = types.stream().map(Type::toString).collect(joining(", ", "(", ")")); throw new IllegalStateException("could not merge " + typesAsString); } Set<Ref> fields = values.stream().flatMap(v -> v.refs.stream()).distinct().collect(toSet()); return new Value(types.get(0), fields); } public static boolean isComposite(BasicValue value) { return value instanceof Value && value.getType().getSort() == Type.OBJECT && ((Value) value).refs.stream().anyMatch(Ref::isComposite); } } 

, . рдЪрд▓реЛ рдЪрд▓рддреЗ рд╣реИрдВ!


 public class FieldsInterpreter extends BasicInterpreter { 

, BasicInterpreter . BasicValue ( , Value extends BasicValue ) .


 public class BasicValue implements Value { public static final BasicValue UNINITIALIZED_VALUE = new BasicValue(null); public static final BasicValue INT_VALUE = new BasicValue(Type.INT_TYPE); public static final BasicValue FLOAT_VALUE = new BasicValue(Type.FLOAT_TYPE); public static final BasicValue LONG_VALUE = new BasicValue(Type.LONG_TYPE); public static final BasicValue DOUBLE_VALUE = new BasicValue(Type.DOUBLE_TYPE); public static final BasicValue REFERENCE_VALUE = new BasicValue(Type.getObjectType("java/lang/Object")); public static final BasicValue RETURNADDRESS_VALUE = new BasicValue(Type.VOID_TYPE); private final Type type; public BasicValue(final Type type) { this.type = type; } } 

( (Value)basicValue ) , , ( " iconst ") .


newValue . , , " ". , this catch . , , . BasicInterpreter BasicValue(actualType) BasicValue.REFERENCE_VALUE . .


 @Override public BasicValue newValue(Type type) { if (type != null && type.getSort() == OBJECT) return new BasicValue(type); return super.newValue(type); } 

entry point. this . , - , , this , BasicValue(actualType) , Value.typedValue(actualType, Ref.thisRef()) . , , this newValue , . , .. , this . this . , . , this 0. , . , , . .


 @Override public BasicValue copyOperation(AbstractInsnNode insn, BasicValue value) throws AnalyzerException { if (wasUpdated || insn.getType() != VAR_INSN || ((VarInsnNode) insn).var != 0) { return super.copyOperation(insn, value); } switch (insn.getOpcode()) { case ALOAD: return typedValue(value.getType(), thisRef()); case ISTORE: case LSTORE: case FSTORE: case DSTORE: case ASTORE: wasUpdated = true; } return super.copyOperation(insn, value); } 

. . , , , тАФ , . , .


 @Override public BasicValue merge(BasicValue v, BasicValue w) { if (v.equals(w)) return v; if (v instanceof Value || w instanceof Value) { if (!Objects.equals(v.getType(), w.getType())) { if (v == UNINITIALIZED_VALUE || w == UNINITIALIZED_VALUE) return UNINITIALIZED_VALUE; throw new IllegalStateException("could not merge " + v + " and " + w); } if (v instanceof Value != w instanceof Value) { if (v instanceof Value) return v; else return w; } return mergeValues(asList((Value) v, (Value) w)); } return super.merge(v, w); } 

. ""? ? рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдирд╣реАрдВред . , .. . , 3 ( ): putfield , putstatic , aastore . . putstatic ( ) . , . putfield aastore . , , . ( ) . , . , тАФ .


 public class Account { private Client client; public Long getClientId() { return Optional.ofNullable(client).map(Client::getId).orElse(null); } } 

, ( ofNullable Optional client value ), . . . , - ofNullable(client) , - map(Client::getId) , .


putfield , putstatic aastore .


 @Override public BasicValue binaryOperation(AbstractInsnNode insn, BasicValue value1, BasicValue value2) throws AnalyzerException { if (insn.getOpcode() == PUTFIELD && Value.isComposite(value2)) { throw new IllegalStateException("could not trace " + value2 + " over putfield"); } return super.binaryOperation(insn, value1, value2); } @Override public BasicValue ternaryOperation(AbstractInsnNode insn, BasicValue value1, BasicValue value2, BasicValue value3) throws AnalyzerException { if (insn.getOpcode() == AASTORE && Value.isComposite(value3)) { throw new IllegalStateException("could not trace " + value3 + " over aastore"); } return super.ternaryOperation(insn, value1, value2, value3); } @Override public BasicValue unaryOperation(AbstractInsnNode insn, BasicValue value) throws AnalyzerException { if (Value.isComposite(value)) { switch (insn.getOpcode()) { case PUTSTATIC: { throw new IllegalStateException("could not trace " + value + " over putstatic"); } ... } } return super.unaryOperation(insn, value); } 

. checkcast . : . тАФ


 Client client1 = ...; Object objClient = client1; Client client2 = (Client) objClient; 

, . , , client1 objClient , . , checkcast .


.


 class Foo { private List<?> list; public void trimToSize() { ((ArrayList<?>) list).trimToSize(); } } 

. , , , . , , , , , . ? , ! . , , , null/0/false. . тАФ


 @JdbcJoinedObject(localColumn = "CLIENT") private Client client; 

, , ORM , . checkcast


 @Override public BasicValue unaryOperation(AbstractInsnNode insn, BasicValue value) throws AnalyzerException { if (Value.isComposite(value)) { switch (insn.getOpcode()) { ... case CHECKCAST: { Class<?> original = reflectClass(value.getType()); Type targetType = getObjectType(((TypeInsnNode) insn).desc); Class<?> afterCast = reflectClass(targetType); if (afterCast.isAssignableFrom(original)) { return value; } else { throw new IllegalStateException("type specification not supported"); } } } } return super.unaryOperation(insn, value); } 

тАФ getfield . тАФ ?


 class Foo { private Foo child; public Foo test() { Foo loopedRef = this; while (ThreadLocalRandom.current().nextBoolean()) { loopedRef = loopedRef.child; } return loopedRef; } } 

, . ? child , child.child , child.child.child ? ? , . , . ,


null.

child, null, , , . Ref.childRef


 if (parent.path.contains(field)) return empty(); 

. , .


" ". . , . , , ( @JdbcJoinedObject , @JdbcColumn ), , . ORM .


, getfield , . , , , . тАФ .


 @Override public BasicValue unaryOperation(AbstractInsnNode insn, BasicValue value) throws AnalyzerException { if (Value.isComposite(value)) { switch (insn.getOpcode()) { ... case GETFIELD: { Optional<Value> optionalFieldValue = childValue((Value) value, (FieldInsnNode) insn, configuration); if (!optionalFieldValue.isPresent()) break; Value fieldValue = optionalFieldValue.get(); if (configuration.isInterestingField(resolveField((FieldInsnNode) insn))) { context.addUsedField(fieldValue); } if (Value.isComposite(fieldValue)) { return fieldValue; } break; } ... } } return super.unaryOperation(insn, value); } 

. , , . , invoke* . , , , . , :


 public long getClientId() { return getClient().getId(); } 

, , . , . . , . ? . . .


 class Account implements HasClient { @JdbcJoinedObject private Client client; public Client getClient() { return client; } } 

Account.client . , . . тАФ , .


 public static class Result { private final Set<Value> usedFields; private final Value returnedCompositeValue; } 

? , . . , .. ( , тАФ ), , areturn , , , *return . MethodNode ( , Tree API) . . тАФ . , ? . .


 private static Value getReturnedCompositeValue(Frame<BasicValue>[] frames, AbstractInsnNode[] insns) { Set<Value> resultValues = new HashSet<>(); for (int i = 0; i < insns.length; i++) { AbstractInsnNode insn = insns[i]; switch (insn.getOpcode()) { case IRETURN: case LRETURN: case FRETURN: case DRETURN: case ARETURN: BasicValue value = frames[i].getStack(0); if (Value.isComposite(value)) { resultValues.add((Value) value); } break; } } if (resultValues.isEmpty()) return null; return mergeValues(resultValues); } 

analyzeField


 public static Result analyzeField(Method method, Configuration configuration) { if (Modifier.isNative(method.getModifiers())) throw new IllegalStateException("could not analyze native method " + method); MethodInfo methodInfo = readMethod(method); MethodNode mn = methodInfo.getMethodNode(); String internalClassName = methodInfo.getInternalDeclaringClassName(); int classAccess = methodInfo.getClassAccess(); Context context = new Context(method, classAccess); FieldsInterpreter interpreter = new FieldsInterpreter(context, configuration); Analyzer<BasicValue> analyzer = new Analyzer<>(interpreter); try { analyzer.analyze(internalClassName, mn); } catch (AnalyzerException e) { throw new RuntimeException(e); } Frame<BasicValue>[] frames = analyzer.getFrames(); AbstractInsnNode[] insns = mn.instructions.toArray(); Value returnedCompositeValue = getReturnedCompositeValue(frames, insns); return new Result(context.getUsedFields(), returnedCompositeValue); } 

, -, . invoke* . 5 :


  1. invokespecial тАФ . , , ( super.call() ).
  2. invokevirtual тАФ . . , .
  3. invokeinterface тАФ , invokevirtual , тАФ .
  4. invokestatic тАФ
  5. invokedynamic тАФ , 7 JSR 292. JVM, invokedynamic ( dynamic). , (+ ), . , Invokedynamic: ? ред

, , , . invokedynamic , . , , , (, ), invokedynamic . , "" . , invokedynamic , .


. , . , . , this , 0? , - , FieldsInterpreter copyOperation . , MethodAnalyzer.analyzeFields " this " " " ( this тАФ ). , . , , . , - . , (- Optional.ofNullable(client) ). .


, invokestatic (.. , this ). invokespecial , invokevirtual invokeinterface . , . , , jvm. invokespecial , , . invokevirtual invokeinterface . , .


 public String objectToString(Object obj) { return obj.toString(); } 

 public static java.lang.String objectToString(java.lang.Object); Code: 0: aload_0 1: invokevirtual #104 // Method java/lang/Object.toString:()Ljava/lang/String; 4: areturn 

, , ( ) . , , . ? ORM . ORM , , . invokevirtual invokeinterface .


рд╣реБрд░реНрд░реЗ! . рдЖрдЧреЗ рдХреНрдпрд╛ рд╣реИ? , ( , this ), ( , ) . !


  @Override public BasicValue naryOperation(AbstractInsnNode insn, List<? extends BasicValue> values) throws AnalyzerException { Method method = null; Value methodThis = null; switch (insn.getOpcode()) { case INVOKESPECIAL: {...} case INVOKEVIRTUAL: {...} case INVOKEINTERFACE: { if (Value.isComposite(values.get(0))) { MethodInsnNode methodNode = (MethodInsnNode) insn; Class<?> objectClass = reflectClass(values.get(0).getType()); Method interfaceMethod = resolveInterfaceMethod(reflectClass(methodNode.owner), methodNode.name, getMethodType(methodNode.desc)); method = lookupInterfaceMethod(objectClass, interfaceMethod); methodThis = (Value) values.get(0); } List<?> badValues = values.stream().skip(1).filter(Value::isComposite).collect(toList()); if (!badValues.isEmpty()) throw new IllegalStateException("could not pass " + badValues + " as parameter"); break; } case INVOKESTATIC: case INVOKEDYNAMIC: { List<?> badValues = values.stream().filter(Value::isComposite).collect(toList()); if (!badValues.isEmpty()) throw new IllegalStateException("could not pass " + badValues + " as parameter"); break; } } if (method != null) { MethodAnalyzer.Result methodResult = analyzeFields(method, configuration); for (Value usedField : methodResult.getUsedFields()) { childValue(methodThis, usedField).ifPresent(context::addUsedField); } if (methodResult.getReturnedCompositeValue() != null) { Optional<Value> returnedValue = childValue(methodThis, methodResult.getReturnedCompositeValue()); if (returnedValue.isPresent()) { return returnedValue.get(); } } } return super.naryOperation(insn, values); } 

. , . , JVMS 1 1. . тАФ . , , . , .. , - , 2 тАФ . , , . , тАФ . , ResolutionUtil LookupUtil .


!



.


, 80% 20% 20% 80% . , , , ?


  • . .


  • . (.. ), . , . , .


     public class Account { private Client client; public Long getClientId() { return Optional.ofNullable(client).map(Client::getId).orElse(null); } } 

    Optional , ofNullable getClientId , , value . , returnedCompositeValue тАФ , , . , , ( ) , . -. , , , " value Optional@1234 Client@5678 " .


  • invokedynamic , . indy , . , . , . , invokedynamic. . . , java.lang.invoke.LambdaMetafactory.metafactory . , , , . java.lang.invoke.StringConcatFactory.makeConcat/makeConcatWithConstants . . toString() . , , , , . , , , /- . jvm, . , , . . . , , . indy . ? indy , тАФ CallSite . . , , LambdaMetafactory.metafactory getValue , . getValue . ( ) . , , , stateless. , ! - , . CallSite ConstantCallSite , MutableCallSite VolatileCallSite . mutable volatile , , ConstantCallSite . "- ". , , . , VM, .




рдЕрдВрддрднрд╛рд╖рдг


- , . - partialGet . , . , , , , " " .


, .

Source: https://habr.com/ru/post/hi409043/


All Articles