yamicha.com's Blog - Presented by yamicha.com
Blog yamicha.com's Blog - 2018/12 の記事
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30] [31]

yamicha.com's Blog
 諸事情により、現在更新休止中。ご了承ください。もし今後ブログを再開することがあるとすれば、その際にはこのブログスクリプトではなく、新しく開発したものによるかもしれません。
 当ブログ管理者についてはこちらをご参照。
開発魔法(737)
社会問題(733)
お知らせ(11)
質問・バトン回答(15)
ゲスト出演(8)
経済・知的財産(150)
ゲーム開発(182)
[Ada] 勝手に補足
- Note
- 金配りの次の一手


- Endless Ultimate Diary
- 銃世界

漢字バトン
- うるる雑記帳
- 漢字接力棒

ツキアイゲノムバトン
- ブログ@うにうに画像倉庫
- あぶ内閣

縺イ縺セ縺、縺カ縺励ヰ繝医Φ
- 月夜のボヤキ
- 騎士サーラバトン
パスワードを使う
名無し (2012/02/27)


開発者解放裁判
yamicha.com (2010/03/14)
Winnyに関しては、私も「純白」とまでは考えておりませんし、使用し..

開発者解放裁判
通りすがり (2010/03/08)
winnyに関しては「ダウンロードソフト板」なんてところを拠点に開発..

新型インフルエンザの恐怖
いげ太 (2009/11/03)
> C#などの「int Some(int , int)」は、F#では「(int * int) ->..

時効に関する思考
yamicha.com (2009/08/31)
>いげ太さんコメントありがとうございます。手元にドキュメントが少..
Homepage
Blog Top
Normal View
List View
Search
Calendar
Comment List
Trackback List
Blog RSS
Send Trackback
Phone Mode
Administrator
yamicha.com
Blog
るううるる。
Source
法令データ提供システム
FindLaw
Development
Java2 Platform SE 6
Java EE 6 API
MySQL Developer Zone
PHP Reference
MSDN Library
Ada Reference Manual
Objective Caml
Python Documentation
Erlang
Prolog Documents
減価償却減税昇格
2006/09/25(Mon)20:59:36
 安倍氏、「法人税」の実質減税を表明。法人税とは何なのでしょう。消費税の一種ですか?それとも所得税?はたまたガソリン税?だと良いのですが。安倍氏が庶民のためになることをするわけがないでしょう。
 トリックは以前に書いておいた通りです。減価償却を拡大することで、法人税を圧縮する方法です。しかし、商学や会計学を学びでもしない限り、「減価償却」なる言葉の意味すら知らないのが普通です。「法人税を何%まで下げる」なら批判を浴びても、「減価償却を拡大する」ならほとんどの人は「?」ですから、批判をやり過ごして法人税を下げられるのです。
 殿様企業は「消費税を10%以上増税してでも法人税を下げて国際競争力を」などとバカげたことをのたまっていますが、恥も誇りもないのですか、あなた方は。例えば、欧米の諸外国では残業手当40%程度は普通です。日本では非常に低い上、払わない企業まであります。これを諸外国並みに引き上げようとすると「国際競争力がなくなる」。諸外国はこの条件で国際競争力を維持しているのですよ。自分が無能と言っているようなものです。
 ではこれについておさらいしておきましょう。以前に「外形標準課税」などというものが東京辺りで銀行に適用されそうになり、大騒ぎになっていましたが、これは赤字でも一定額の税を要求します。しかし、通常の企業においては、利益に対して法人税が計算されます。利益がなければ法人税は発生せず、利益があってもその度合いによります。
 ここまでが法人税の基本です。石を投げられそうですが、法人税は仕入原価や企業規模に対してではなく、利益に対してかけるものであるということです。つまり、仕入原価や諸経費500万円を売り上げより減算した末、純利益500万円なら法人税がありますが、仮に1000億円売り上げても赤字なら、ない袖は振れません。
 では減価償却とは。10年前に建てた建造物1000万円と最近建てた建造物1000万円では、確かに金額は同じなのですが、経年劣化などにより同じ価値があるとみなすことはできません。それなのに帳簿でいつまで経っても建物が1000万円とされるのは不適切です。これでは、固定資産を5000万持っている企業が2つあったとして、かたや新築ビルと新車、かたやオンボロ建造物と旧式車が同じ評価になってしまいます。
 そこで必要なのが減価償却です。といっても、あらゆる建造物、機械、運搬具、備品などについて毎年価値を測定するのでは無意味ですから、毎年決まった額、もしくは決まった比率で減額していくことになっています。こうしてなされた「減価償却」は損失とされ、利益から控除されます
 毎年の減価償却額を決めるのに重要なのが「元の価値」「耐用年数」「残存価値」です。定額法の場合、大体は「毎年の償却額 = (元の価値 - 残存価値) / 耐用年数」で表されます。最初は元の価値(購入金額など)だけの価値があり、毎年少しずつ価値が減っていき、耐用年数を超えると残存価値だけの価値が残ります。耐用年数を超えた後は、もはや償却される余地がなくなったものとして、処分あるいは売却時まで残存分の価値が残ります。また、耐用年数は様々な備品ごとに規定されているようです。
 ここからがポイントですが、日本では必ず5%以上の価値を残さなければなりませんでした。1億円で建物や設備を購入した場合、耐用年数が過ぎても必ず500万以上の価値が残ります。しかし、安倍氏はどうやらこれを「0%」にしたいようです。どうなるかはお分かりの通りです。
 1億円で購入した設備について、500万すら残す必要がなくなりますので、0円まで償却してしまうことができます。これできっちり全額償却できるため、利益をその分圧縮できます。すると、実際には何も変わっていないにもかかわらず、帳簿の関係で利益を圧縮することができ、法人税が減少するのです。
 実際には赤字の際にはさらに赤字が拡大するなどデメリットもありますが、これは黒字続きで赤字転落が当面考えられず、裏でリストラや無賃労働を強制しているような殿様大企業はウハウハでしょうな。逆に、ギリギリで設備も買い換えられず、赤字が続いているような苦しい企業は恩恵どころではないでしょう。安倍氏の綿密で計算しつくされた策にはかないません

 安倍氏に関しては、もはや大学9月入学自体にも反対しておきます。実際のところ9月化そのものには賛成なのですが(世界標準でもあり、何より冬の寒く体調を崩しやすい時期に受験など常識がないとしか考えられないため。病弱な人には非常に不公平では)、安倍氏が9月化にこだわる理由は「どうしても奉仕活動を強制させたいから」のようです。これが美しい国とはちゃんちゃらおかしいですね。私の主張とでは手段は同じですが目的が全く違います。
 強制奉仕活動の愚かさについては過去の記事で詳しく分析していますので、必要ならそちらをお読みいただくとして、安倍氏は「奉仕活動をしなければ大学に入れないようにする」とまで言い始めています。私はこのようなくだらない脅迫を絶対に許しません。「強制でもやるのは有意義」とは安倍氏の弁ですが、どこがどのように有意義なのだかさっぱり。確かに、ひたすら打算でのみ動き、他人より自分の利益だけをとことん重視する人間は大量に作れるでしょうが。
 また、大学の関係者様各位には、もし安倍氏がこのような酔狂なものを導入したとしても、圧力に屈さず奉仕活動を判断材料にしないようお願いします。所詮は点数稼ぎのための奉仕活動、評価すべき点はないのですから。

 この前散々苦しめられたクラスローダ。今回は概念を理解してしまいます。これが開発者の執念というものでして。
 まずJavaですが、これはC/C++言語で作られており、クラスファイルも変数と構造体の集まりです。クラスの解決には「クラスローダ」なる仕組みが使われており、クラスローダがクラスをロードすることでクラスが使えるようになっています。クラスのロードとは、すなわちこのクラスファイルをJavaにパースさせる行為です。クラスローダはClassLoaderクラスによって表されます(ところでClassLoaderクラスは誰がロードしているのでしょう)。
 ということは、クラスファイルらしきものさえあれば、クラスが使えてしまうものと考えられます。何やらすさまじい話ではありますが。実際、byte[]配列からクラスを構築することができるようです。そんなこんなで作ったのがこちら。
public class Pow{
	private int value;
	public Pow(int v){
		value = v;
	}
	public int getPow(int l){
		int answer = value;
		for(int i = 0; i < l - 1; i++){
			answer *= value;
		}

		return answer;
	}
}
 いわゆるテスト用のクラスです。コンストラクタで元の数値を渡し、メソッドでさらに数値を渡すと、累乗の結果を返してくれます。これをコンパイルし、生成されたPow.classファイルをデータベースのBLOBカラムに登録しておきます。
 通常、データベースに登録されたクラスを読み取ることはできません。classesなりlibなりのディレクトリに投げ入れておく必要があります。もしくはクラスパスを通して実行することが必要です。しかしながら、今回はそうしたことはできません。一体どうしたものでしょうか。
 このような場合こそ、クラスローダを使う時です。
class YClassLoader extends ClassLoader{
	public YClassLoader(){
		super();
	}

	public Class databaseResolve(String name , Connection c , 
		String fname , boolean force) 
		throws SQLException{
		byte b[] = null;

		PreparedStatement ps = c.prepareStatement(
			"SELECT data FROM datatable WHERE name = ?");
		ps.setString(1 , fname);
		ResultSet rs = ps.executeQuery();
		if(rs.next())
			b = rs.getBytes("data");
		ps.close();

		if(b == null)
			return null;

		if(force){
			return forceDefine(name , b , 0 , b.length);
		}else{
			return define(name , b , 0 , b.length);
		}
	}
	public Class define(String name , byte b[] , int off , int len)
		throws ClassFormatError{
		if(findLoadedClass(name) == null)
			return null;

		return forceDefine(name , b , off , len);
	}
	public Class forceDefine(String name , byte b[] , int off , int len)
		throws ClassFormatError{
		return defineClass(name , b , off , len);
	}
}
 これを使うと、データベースからクラスを読み込んでくれます。databaseResolveの引数ですが、1つ目は推測されるクラス名、2つ目がSQL接続、3つ目がデータベース「datatable」上でのnameカラムの名前(同テーブルのdataがクラスファイルを保持したBLOBカラムであるとする)、4つ目が「すでに同じクラスがある場合の動作」になっています(trueで再読み込み)。
 では、実際にこのようにプログラムを
Pow p = new Pow(10);
int value = p.getPow(5);
 組めません。javacでスタブのクラスパスを通せばコンパイルはできそうですが、JSPにおいてはPowなるクラスは存在しないため、このようにプログラムを組むことはできません。ということで、このようになります。
// 接続
Context ct = new InitialContext();
DataSource ds = (DataSource)ct.lookup("java:/comp/env/jdbc/MySQLJSP");
Connection cn = ds.getConnection();

// クラスローダの構築と取り出し
YClassLoader y = new YClassLoader();
y.databaseResolve("Pow" , cn , "Pow.class" , true);
cn.close();

// クラス生成
Class c = Class.forName("Pow" , true , y);
Constructor con = c.getConstructor(int.class);
Method m = c.getMethod("getPow" , int.class);

Object pow = con.newInstance(new Integer(4));
int value = ((Integer)m.invoke(pow , 3)).intValue();

out.println(value);
 これで「64」が得られます。しかしまあ、何と面倒極まりないのでしょうか。このようなプログラムを組む必要があるなら、あらかじめビジネス インタフェース(これはServletのlibなりclassesに入れておく)を用意し、それを継承したクラスにはデフォルトコンストラクタを用意しておき、クラス生成時のみClassを使って「BusinessInterface obj = (BusinessInterface)Class.forName(name , true/false , classloader).newInstance()」とでもすれば良いのではないでしょうか。
 この場合、クラスを更新したり、後で新しいクラスを追加したり、あるいはデータベースをソースとしたい場合であっても、たぶん動きます。インタフェースに登録されていない独自メソッドを使う際には、どうしてもリフレクトするしかありませんが。
 また、クラスローダに関しては、とあるクラスローダから何かを生成した場合、そのクラスローダで作られたオブジェクトでは生成されたクラスローダを使う、のような解決方法になるようです。この点、非常にややこしいのですが、
public class CLoader{
	public static void main(String args[]) throws Exception{
		File f = new File(
			"this class directory\\CLoader.class");
		byte bs[] = new byte[(int)f.length()];
		InputStream is = new FileInputStream(f);
		is.read(bs);
		is.close();

		CLoader c = new CLoader();
		System.out.println("UseClassLoader : " + 
			c.getClass().getClassLoader());
		c.classLoaderName();

		YClassLoader y = new YClassLoader();
		y.forceDefine("CLoader" , bs , 0 , bs.length);

		Class cls = Class.forName("CLoader" , true , y);
		Object cl = cls.newInstance();
		System.out.println("UseClassLoader : " + 
			cl.getClass().getClassLoader());

		Method m = cls.getMethod("classLoaderName");
		m.invoke(cl);
	}
	public void classLoaderName(){
		CLoader c = new CLoader();
		System.out.println("SystemClass : " + 
			ClassLoader.getSystemClassLoader());
		System.out.println("LoadedClass : " + 
			c.getClass().getClassLoader());
	}
}

class YClassLoader extends ClassLoader{
	public YClassLoader(){
		super();
	}
	public Class define(String name , byte b[] , int off , int len)
		throws ClassFormatError{
		if(findLoadedClass(name) == null)
			return null;

		return forceDefine(name , b , off , len);
	}
	public Class forceDefine(String name , byte b[] , int off , int len)
		throws ClassFormatError{
		return defineClass(name , b , off , len);
	}
}
 このクラスの場合、YClassLoaderのオブジェクトはクラスファイルを読み取って生成されます。無論、デフォルトのローダと同じものを読み取りはするものの、違うものとして扱われます。なお、ClassLoaderにはresolveClassというClassからクラスを解決するものがありますが、これを使ってデフォルトのローダからClassを渡した場合、新しいクラスローダの側でもデフォルトのローダで作ったクラスが使われるようです(新しくロードされるのではない模様)。
 さて、上記クラスについてですが、まずCLoader.mainに関してはデフォルトのクラスローダから呼び出されます。すなわち、そこでCLoaderを作っても、そのCLoaderはデフォルトクラスローダの所属になります。
 しかし、その下ではYClassLoader(一応補足しておきますと、yamicha.com ClassLoader の意味)が生成され、それがCLoader.classのデータを読み取り、クラスを構築しています。この時点でデフォルトのローダで読み込まれたものとは内容が同一でありながら実体は別物のクラスが誕生します。無論、デフォルトのローダ上でのクラスと互換性はなく、よって新しいローダで読んだクラスをデフォルトのローダで読んだ型にキャストすることはできません。中身は同じだというのに。
 さて、その下でYClassLoaderからクラスが解決されて新しいインスタンスが生成されますが、この時点で生成されたインスタンスはYClassLoader所属になります。さらに、そのインスタンスからclassLoaderNameメソッドを呼び出すと、そのメソッド内で生成されるCLoaderのインスタンスもYClassLoaderから作られたことになります。ただし、システムクラスローダは常にデフォルトローダのものになり、変わりません。
 ということで、
// 普通に(newで)生成されたインスタンスの所属クラス
UseClassLoader : sun.misc.Launcher$AppClassLoader@11b86e7
// ClassLoader.getSystemClassLoader();
SystemClass : sun.misc.Launcher$AppClassLoader@11b86e7
// classLoaderName()内でインスタンスを生成した際の所属ローダ
LoadedClass : sun.misc.Launcher$AppClassLoader@11b86e7

// 以下、YClassLoaderから生成したインスタンスによるもの
// forName(...).newInstance(); により生成したクラス
UseClassLoader : YClassLoader@19821f
// そのメソッドからgetSystemClassLoader()してもクラスローダは変わらず
SystemClass : sun.misc.Launcher$AppClassLoader@11b86e7
// そのメソッド内でインスタンスを作った場合
LoadedClass : YClassLoader@19821f
 こうなるわけです(注釈・一部改行は私が付加)。要するに、DriverManagerはこの規則に基づいてドライバを探していたわけです。
 とすると、ビジネス インタフェースを使う場合にも、一枚クラスをかませなければならないかもしれません。特定のクラスをインタフェース経由で扱おうにも、そのインタフェースに互換性がないとみなされれば意味がありませんから。かませたクラスには「パイプ」として動作していただきます。
 または、インタフェースをresolveClassして、クラスのみをdefineClass()で読み取って、それで互換性が保てるようならそれが楽そうなのですが、はてさて。実験あるのみです。
// NewLoader.java
public class NewLoader{
	public static void main(String args[]) throws Exception{
		File f = new File("this class directory\\IFInstance.class");
		byte bs[] = new byte[(int)f.length()];
		InputStream is = new FileInputStream(f);
		is.read(bs);
		is.close();

		YClassLoader y = new YClassLoader();
		y.resolve(BIF.class);
		y.forceDefine("IFInstance" , bs , 0 , bs.length);

		BIF bif = (BIF)Class.forName("IFInstance" , true , y).newInstance();
		System.out.println(bif.getValue());
	}
}

class YClassLoader extends ClassLoader{
	public YClassLoader(){
		super();
	}
	public Class define(String name , byte b[] , int off , int len)
		throws ClassFormatError{
		if(findLoadedClass(name) == null)
			return null;

		return forceDefine(name , b , off , len);
	}
	public Class forceDefine(String name , byte b[] , int off , int len)
		throws ClassFormatError{
		return defineClass(name , b , off , len);
	}
	public void resolve(Class c){
		resolveClass(c);
	}
}

// BIF.java
public interface BIF{
	String getValue();
}

// IFInstance.java
public class IFInstance implements BIF{
	public String getValue(){
		// 実はデフォルトのローダからコールされていた、という
		// オチを避けるため、ローダを確認する
		System.out.println(getClass().getClassLoader());
		return "何らかのデータ";
	}
}
 大変いい加減ですが、そこには目をつぶってください。これですが、何と動いてしまいます。上記で宣言として使っているのはあくまでBIFのみであるため、IFInstanceはコンパイルに含める必要すらありません。後からコンパイルしても、パスさえ修正すればどこに置いても構いません。さらに言えば、データベースやサーバー上にしかないものを取りに行くだけでも(たぶん)構いません。
 これのポイントは、BIF(Business Interface)をresolveClassで解決することにより、2つのローダの間でBIFに互換性を持たせている点です。双方のローダで同じように扱えるため、インタフェースとしての利用が可能です。
 つまり、クラスを特別な方法でロードした上、それをデフォルトのローダの管轄でも普通に使いたい場合、ビジネス インタフェースを定義しておき、そのインタフェースに互換性を持たせれば良い、ということになります。
 クラスローダも研究すると面白いものです。

 SQLですが、残すところはあと3回。ということで、開発魔法に彩を添えてくれる出演ゲスト様でも募集してみます。ただし、これまでに私との会話などでキャラの存在が話に上がるなどして、私がそれを明確に認識しているのが条件です。存在さえ分かっていれば何とかなりますが、誰とも分からないキャラをいきなり「出せ」というのは無理というもので。
 その後も気が向いてネタがあればぼちぼち書くかもしれませんが、シリーズとしては100で終わります。本当はもっとゲストの出演機会を多くしたかったのですが、今からがんばってもせいぜい2回程度ですか。大円団的な終わり方も面白そうですが、人数が多くなるとクエリが大変なことになりますし、どうしましょう。
カテゴリ [開発魔法][社会問題] [トラックバック 0][コメント 0]
<- 前の記事を参照 次の記事を参照 ->

- Blog by yamicha.com -